You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译时生成指定最大值以内素数的std::array,如何消除代码重复?

避免生成素数std::array时重复调用make_primes的方法

你需要生成包含不超过30的素数的std::array,当前代码中重复调用make_primes(MAX_PRIME)来获取素数列表和数组大小,导致冗余。以下是两种解决方法:

原始代码问题点

在初始化primes数组的lambda中,先后两次调用make_primes(MAX_PRIME):一次获取素数vector,另一次获取vector的size作为std::array的模板参数,造成不必要的重复计算。

#include <iostream>
#include <cstdint>
#include <vector>
#include <array>

using namespace std;

constexpr vector<int> make_primes(int max_prime) noexcept
{
    vector<int> primes;

    primes.push_back(2);
    for (int p = 3; p < max_prime; )
    {
        primes.push_back(p);

        int i;
        do {
            p += 2;

            i = 1;
            for (; i < primes.size(); ++i)
            {
                if ((p % primes[i]) == 0)
                    break;
            }
        }
        while (i != primes.size());
    }
    
    return primes;
}

constexpr int MAX_PRIME = 30;  // 2 3 5 7 11 13 17 19 23 29

constexpr auto primes {
    []() {
        auto primes = make_primes(MAX_PRIME);
        constexpr auto N = make_primes(MAX_PRIME).size(); // 重复调用

        std::array<int, N> arr;
        for (int i = 0; i < arr.size(); ++i)
            arr[i] = primes[i];
        return arr;
    }()
};

int main()
{
    cout << primes.size() << ':';
    for (int x : primes)
        cout << ' ' << x;
    cout << endl;

    return 0;
}

方案1:提前定义constexpr素数vector(C++17及以上)

将make_primes的结果提前存储为一个constexpr vector,后续直接复用它的元素和大小,只调用一次生成函数:

#include <iostream>
#include <cstdint>
#include <vector>
#include <array>

using namespace std;

constexpr vector<int> make_primes(int max_prime) noexcept
{
    vector<int> primes;
    if (max_prime < 2) return primes;

    primes.push_back(2);
    for (int p = 3; p <= max_prime; )
    {
        primes.push_back(p);

        int i;
        do {
            p += 2;
            i = 1;
            for (; i < primes.size(); ++i)
            {
                if ((p % primes[i]) == 0)
                    break;
            }
        } while (i != primes.size() && p <= max_prime);
    }
    
    return primes;
}

constexpr int MAX_PRIME = 30;
constexpr auto primes_vec = make_primes(MAX_PRIME); // 仅调用一次

constexpr std::array<int, primes_vec.size()> primes = []{
    std::array<int, primes_vec.size()> arr{};
    for (size_t i = 0; i < arr.size(); ++i)
        arr[i] = primes_vec[i];
    return arr;
}();

int main()
{
    cout << primes.size() << ':';
    for (int x : primes)
        cout << ' ' << x;
    cout << endl;
    return 0;
}

方案2:在constexpr lambda内复用vector(C++20及以上)

C++20放宽了constexpr上下文的限制,允许在lambda内用constexpr变量作为非类型模板参数,直接在lambda内部生成一次vector并复用:

#include <iostream>
#include <cstdint>
#include <vector>
#include <array>

using namespace std;

constexpr vector<int> make_primes(int max_prime) noexcept
{
    vector<int> primes;
    if (max_prime < 2) return primes;

    primes.push_back(2);
    for (int p = 3; p <= max_prime; )
    {
        primes.push_back(p);

        int i;
        do {
            p += 2;
            i = 1;
            for (; i < primes.size(); ++i)
            {
                if ((p % primes[i]) == 0)
                    break;
            }
        } while (i != primes.size() && p <= max_prime);
    }
    
    return primes;
}

constexpr int MAX_PRIME = 30;

constexpr auto primes = []() {
    constexpr auto primes_vec = make_primes(MAX_PRIME); // 仅调用一次
    std::array<int, primes_vec.size()> arr{};
    for (size_t i = 0; i < arr.size(); ++i)
        arr[i] = primes_vec[i];
    return arr;
}();

int main()
{
    cout << primes.size() << ':';
    for (int x : primes)
        cout << ' ' << x;
    cout << endl;
    return 0;
}

两种方案都能避免重复调用make_primes,方案1兼容C17,方案2利用C20特性让代码更紧凑。

内容的提问来源于stack exchange,提问作者Mishka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:34:58