编译时直接计算数列存入constexpr变量,避免重复计算素数长度
编译期生成素数并存储到constexpr变量的优化方案
核心问题解决方案
1. 无需预先计算大小的编译期存储
在C++20及以后,std::vector支持constexpr操作,可直接在编译期用它收集素数,无需预先知晓元素数量。若坚持使用std::array,也能基于constexpr vector的编译期size()值来构造array,全程在编译阶段完成。
2. 避免重复计算(移除get_primes_size函数)
原代码两次遍历判断素数,造成重复计算。通过一次遍历同时完成素数收集与数量统计即可解决:先用constexpr vector存储所有素数,再转换为array,每个数仅需调用一次is_prime判断。
3. 编译期std::vector转std::array的可行性
完全可行,C++20及以上版本中,constexpr vector的size()是编译期常量,可直接用于指定array的大小,再通过编译期循环完成元素复制。
优化后的代码示例
#include <array> #include <vector> #include <iostream> constexpr bool is_prime(int n) { if (n <= 1) return false; if (n == 2) return true; if (n % 2 == 0) return false; // 修正原函数边界问题:i*i <=n 避免漏判平方数 for (int i = 3; i * i <= n; i += 2) { if (n % i == 0) { return false; } } return true; } template <int UpperLimit> consteval auto get_primes() { std::vector<int> temp_primes; // 一次遍历完成素数收集 for (int i = 2; i <= UpperLimit; ++i) { if (is_prime(i)) { temp_primes.push_back(i); } } // 编译期将vector转换为array std::array<int, temp_primes.size()> primes_arr{}; for (std::size_t idx = 0; idx < temp_primes.size(); ++idx) { primes_arr[idx] = temp_primes[idx]; } return primes_arr; } // 编译期生成素数数组 constexpr auto primes = get_primes<1000>(); int main() { std::cout << "1000以内素数总数:" << primes.size() << '\n'; for (int prime : primes) { std::cout << prime << ' '; } std::cout << '\n'; return 0; }
代码说明
- 修正原
is_prime函数的边界错误:原代码i*i < n会漏判4、9这类平方数,改为i*i <=n并增加偶数快速判断,提升效率。 - 使用
consteval确保函数完全在编译期执行,不会生成运行时代码。 - 仅一次遍历收集素数,避免了原代码两次调用素数判断的重复计算。
- 借助C++20的constexpr vector特性,先动态收集素数再转换为固定大小的array,兼顾灵活性与性能。
内容的提问来源于stack exchange,提问作者Andy Lee
相关产品推荐
相关产品推荐

