C ++将静态成员std :: array元素初始化/填充为特定值

时间:2019-06-20 00:11:23

标签: c++ arrays static-members array-initialization

我想知道是否有适当的方法来做到这一点。

举个例子:

struct Test {
    static std::array<unsigned, 123> data;
};

std::array<unsigned, 123> Test::data = {};

如果我想将data中的所有元素设置为某个值,例如5。

我可以做这样的事情:

struct Test {
    static std::array<unsigned, 123> data;
private:
    static decltype(data) init_data_arr() {
        decltype(data) arr = {};
        arr.fill(5);
        return arr;
    }
};

std::array<unsigned, 123> Test::data = Test::init_data_arr();

但是然后我要分配一个额外的内存数组,并在所有内存上进行复制,这似乎并不理想。

另一个不占用大量内存的选项如下:

struct Test {
    static bool is_init;
    static std::array<unsigned, 123> data;

    Test() {
        if (!is_init) {
            is_init = true;
            data.fill(5);
        }
    }
};

bool Test::is_init = false;
std::array<unsigned, 123> Test::data = {};

但是现在在构建Test结构时,我还有额外的开销。

现在,我知道您可以像这样初始化Pod数组:std::array<int, 3> a = {1, 2, 3};,但是对于N大小的数组,这将很快变得难以维护。

我遇到的每个解决方案似乎都在数组类上使用fill成员函数,但始终将数组视为非静态成员变量,或者将其初始化为main,这两个都不会。不能真正帮助我解决问题。

编辑: 我创建了这个实用程序标头,概括了第二个选项。     #pragma一次

#include <utility>
#include <iterator>
#include <algorithm>
#include <type_traits>

namespace Utils {

    template<typename Container>
    using element_type_t = std::remove_reference_t<decltype(*std::begin(std::declval<Container&>()))>;

    template<class Container>
    static Container create_filled_container(const element_type_t<Container>& value) {
        Container container = {};
        std::fill(container.begin(), container.end(), std::move(value));
        return container;
    }

}

这可能需要进一步改进,但似乎可以解决。用法如下:

std::array<unsigned, 123> Test::data = Utils::create_filled_container<decltype(data)>(456);

将所有元素设置为您指定的任何内容。

Edit2: 因此,我进行了一些更多的测试,看起来像调用函数来填充数组而不是手动进行操作并不总是产生相同的程序集。

我已经设置了一个演示here

Edit3: 修改了一些东西,使其可以是constexpr,以下是其当前形式:

template<class Container>
static constexpr Container create_filled_container(const element_type_t<Container>& value) {
    Container container = {};

    for (auto it = container.begin(); it != container.end(); ++it)
        *it = value;

    return container;
}

现在会产生相同的程序集。

1 个答案:

答案 0 :(得分:1)

使用constexpr函数或lambda对其进行初始化。没有运行时代码生成。

#include <array>
#include <iostream>

template <unsigned len, unsigned val>
constexpr std::array<unsigned, len> initialize_array()
{
    std::array<unsigned, len> ret{};
    for (int i = 0; i < len; i++)
        ret[i] = val;
    return ret;
}

struct Test {
    constexpr static std::array<unsigned, 123> data{ initialize_array<123,5>() };
};

int main() {
    std::cout << Test::data[4] << "\n";
}