为什么std::vector和std::array的C++initializer_list行为不同

Why is the C++ initializer_list behavior for std::vector and std::array different?

本文关键字:std list vector array 为什么 C++initializer      更新时间:2023-10-16

代码:

std::vector<int> x{1,2,3,4};
std::array<int, 4> y{{1,2,3,4}};

为什么我需要std::array的双大括号?

std::array<T, N>是一个聚合:它没有任何用户声明的构造函数,甚至没有一个接受std::initializer_list的构造函数。使用大括号的初始化是使用聚合初始化执行的,这是继承自C.的C++特性

聚合初始化的"旧式"使用=:

std::array<int, 4> y = { { 1, 2, 3, 4 } };

使用这种老式的聚合初始化,可能会省略额外的大括号,因此这相当于:

std::array<int, 4> y = { 1, 2, 3, 4 };

然而,这些额外的大括号只能在"形式为T x = { a };的声明"(C++11§8.5.1/11)中删除,也就是说,当使用旧式=时。此允许省略大括号的规则不适用于直接列表初始化。这里的脚注写道:"括号不能在列表初始化的其他用途中被忽略。"

有一份关于该限制的缺陷报告:CWG缺陷#1270。如果所提出的解决方案被采用,括号省略将被允许用于其他形式的列表初始化,并且以下内容将被很好地形成:

std::array<int, 4> y{ 1, 2, 3, 4 };

(向Ville Voutilainen提供查找缺陷报告的帽子提示。)

因为std::vector提供了一个接受std::initializer_list<T>的构造函数,而std::array没有构造函数,而且{1, 2, 3, 4}支持的init列表实际上没有被解释为std::initializer_list,而是std::array的内部C样式数组的聚合初始化(这就是第二组大括号的来源:一个用于std::array,一个用于内部C样式成员数组)。