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


74

码:

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

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


1
您实际上是否需要为设置第二组大括号std::array,还是只是收到警告?std::array<int,4> y{1,2,3,4};为我工作。
bames53

3
@ bames53:GCC在编译时是错误的。
Xeo 2012年

14
@Xeo:编译带有警告的格式错误的程序并非“错误”。
史蒂夫·杰索普

3
@史蒂夫:是的。假设是非便携式的?
Xeo 2012年

2
@Xeo:是的,-Werror无论如何,我都会使用自己编写的代码,因此它不会损害我的可移植性。如果其他人是轻量级的,或者需要包括由轻量级的人编写的头文件,则里程数可能会有所不同:-)
Steve Jessop 2012年

Answers:


63

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提交有关查找缺陷报告的提示)。


3
那么这是针对抽象模型的失败array吗?
Mark Ransom

1
@Mehrdad:这统一的。什么是不统一的是,你初始化两个完全不同类型的事实。
Nicol Bolas'7

5
@NicolBolas:我认为一致性的全部目的是对不同类型使用相同的初始化语法?(是的,我确实了解正在发生的事情……我只是说这对用户来说不是“统一的”,无论是否有任何解释。)
user541686

@MarkRansom:好吧,这是一种语言的怪癖,因为它std::array<int> y = {1,2,3,4};与Clang的警告一起建议使用括号,而不是关于不允许“使用直接列表初始化时在子对象的初始化周围省略括号”的硬错误。
Xeo 2012年

1
@Xeo:实际上,括号初始化在聚合初始化中是允许的,但是(显然)在使用直接列表初始化语法时是不允许的。
James McNellis'7

29

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.