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

Sun*_*min 67 c++ stl c++11

码:

std::vector<int> x{1,2,3,4};
std::array<int, 4> y{{1,2,3,4}};
Run Code Online (Sandbox Code Playgroud)

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

Jam*_*lis 61

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

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

std::array<int, 4> y = { { 1, 2, 3, 4 } };
Run Code Online (Sandbox Code Playgroud)

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

std::array<int, 4> y = { 1, 2, 3, 4 };
Run Code Online (Sandbox Code Playgroud)

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

有关此限制的缺陷报告:CWG缺陷#1270.如果采用提议的解决方案,将允许使用大括号来进行其他形式的列表初始化,并且以下内容将是格式良好的:

std::array<int, 4> y{ 1, 2, 3, 4 };
Run Code Online (Sandbox Code Playgroud)

(帽子向Ville Voutilainen提示找到缺陷报告.)

  • @NicolBolas:我认为统一的重点是对不同类型使用相同的初始化语法?(是的,我确实理解发生了什么......我只是说它对用户来说并不"统一",无论是否有解释.) (5认同)
  • 因此,为"数组"呈现抽象模型的失败? (3认同)
  • 我不知道这个; 不错. (2认同)

Xeo*_*Xeo 25

因为std::vector提供了一个构造函数,它接受一个std::initializer_list<T>,而std::array没有构造函数,并且{1, 2, 3, 4}支撑的init-list实际上并没有被解释为std::initializer_list,而是内部C风格数组的聚合初始化std::array(这是第二组括号的来源:一个for std::array,一个用于内部C风格的成员数组).