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

Hex*_*own 1 c++ arrays static-members array-initialization

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

举个例子:

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

std::array<unsigned, 123> Test::data = {};
Run Code Online (Sandbox Code Playgroud)

如果我想将 中的所有元素设置为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();
Run Code Online (Sandbox Code Playgroud)

但随后我会分配额外的数组内存并对其进行复制,这似乎并不理想。

另一种内存密集程度较低的选项是这样的:

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 = {};
Run Code Online (Sandbox Code Playgroud)

但现在我在构建测试结构时有额外的开销。

现在我知道你可以像这样初始化 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;
    }

}
Run Code Online (Sandbox Code Playgroud)

这可能还可以进一步改进,但似乎有效。用法如下:

std::array<unsigned, 123> Test::data = Utils::create_filled_container<decltype(data)>(456);
Run Code Online (Sandbox Code Playgroud)

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

Edit2:所以我做了一些更多的测试,看起来调用一个函数来填充数组与手动执行它并不总是产生相同的程序集。

在这里设置了一个演示!

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;
}
Run Code Online (Sandbox Code Playgroud)

现在生产相同的组件。

dou*_*oug 5

使用 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";
}
Run Code Online (Sandbox Code Playgroud)