使用常量值初始化 std::array

Initializing a std::array with a constant value

本文关键字:std array 初始化 常量      更新时间:2023-10-16

我需要用常量值初始化std::array的所有元素,就像可以用std::vector一样

#include <vector>
#include <array>
int main()
{
std::vector<int> v(10, 7);    // OK
std::array<int, 10> a(7);     // does not compile, pretty frustrating
}

有没有办法优雅地做到这一点?

现在我正在使用这个:

std::array<int, 10> a;
for (auto & v : a)
v = 7;

但我想避免使用显式代码进行初始化。

使用std::index_sequence,您可以执行以下操作:

namespace detail
{
template <typename T, std::size_t ... Is>
constexpr std::array<T, sizeof...(Is)>
create_array(T value, std::index_sequence<Is...>)
{
// cast Is to void to remove the warning: unused value
return {{(static_cast<void>(Is), value)...}};
}
}
template <std::size_t N, typename T>
constexpr std::array<T, N> create_array(const T& value)
{
return detail::create_array(value, std::make_index_sequence<N>());
}

随着使用情况

auto a = create_array<10 /*, int*/>(7); // auto is std::array<int, 10>

std::fill解决方案相反,它处理非默认的可构造类型。

唉不是;std::array支持聚合初始化,但这还不够。

幸运的是,您可以使用std::fill,甚至std::array<T,N>::fill,从 C++20 开始,随着后者变得constexpr,它优雅

。参考: https://en.cppreference.com/w/cpp/container/array/fill

你可以执行以下操作

std::array<int, 10> a; 
a.fill(2/*or any other value*/);

或者使用算法头文件中的std::fill。 包含算法头文件使用

#include <algorithm>

从 C++17 开始,您可以编写一个 constexpr 函数来有效地设置数组,因为元素访问器现在是 constexpr。此方法也适用于设置初始值的各种其他方案:

#include <array>
template<typename T, size_t N>
constexpr auto make_array(T value) -> std::array<T, N>
{
std::array<T, N> a{};
for (auto& x : a)
x = value;
return a;
}
int main()
{
auto arr = make_array<int, 10>(7);
}

如前所述,fill解决方案不适用于非默认的可构造类型。index_sequence解决方案是正确的,但有点冗长。

给定一个值t(任何类型(和一个编译常量N,下面计算出一行中所需的解决方案。

std::apply([&](auto... dummy) {return std::array{(dummy, t)...};}, std::array<int, N>{});

在此处查看完整代码:https://godbolt.org/z/jcq4fqMsE

此解决方案可以应用于 C++17,并对早期版本进行一些修改。

std::array类型是支持列表初始化的聚合:

std::array<int, 10> a{2, 2, 2, 2, 2, 2, 2, 2, 2, 2};

它还支持聚合初始化:

std::array<int, 10> a = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2};

这对于长数组来说既不方便又容易出错,您最好使用像 Jarod42 这样的解决方案。

这可以通过创建一个返回所需数组的函数模板来相当容易地完成,如下所示。甚至可以在编译时初始化数组!(请参阅答案末尾给出的 C++17 示例演示(。

template<std::size_t N> std::array<int, N> make_array(int val)
{
std::array<int, N> tempArray{};    //create local array
for(int &elem:tempArray)           //populate it 
{
elem = val;                     
}
return tempArray;                   //return it
}
int main()
{
//---------------------V-------->number of elements  
auto arr  = make_array<10>(7);
//------------------------^---->value of element to be initialized with

//lets confirm if all objects have the expected value 
for(const auto &elem: arr)
{
std::cout << elem << std::endl; //prints all 7 
}

}

演示


另请注意,甚至可以在编译时使用 C++17 执行此操作。演示 C++17

C++20开始,rangesfill

std::array<int, 10> a2;
std::ranges::fill(a2, 10);

此外,如果数组很小(对于较大的数组,它可能看起来很奇怪(,则从C++17(参数推导(

auto a = std::array{2,2,2,2};