这是因为std::array是一个聚合,因此会执行聚合初始化,这在草案 C++11 标准部分8.5.4
[dcl.init.list]中有介绍,其中说:
类型 T 的对象或引用的列表初始化定义如下:
如果初始值设定项列表没有元素并且 T 是具有默认构造函数的类类型,则该对象是值初始化的。
否则,如果 T 是一个聚合,则执行聚合初始化 (8.5.1)。
double ad[] = { 1, 2.0 }; // OK
int ai[] = { 1, 2.0 }; // error: narrowing
struct S2 {
int m1;
double m2, m3;
};
S2 s21 = { 1, 2, 3.0 }; // OK
S2 s22 { 1.0, 2, 3 }; // error: narrowing
S2 s23 { }; // OK: default to 0,0,0
我们可以看看它是否不是一个聚合,然后列表继续说:
- 否则,如果 T 是 std::initializer_list 的特化,则按如下所述构造一个 initializer_list 对象,并用于根据从相同类型的类 (8.5) 中初始化对象的规则来初始化该对象。
- 否则,如果 T 是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载决议(13.3、13.3.1.7)选择最佳构造函数。如果需要缩小转换(见下文)来转换任何参数,则程序格式错误。
我们可以确认std::array
是来自23.3.2.1
[array.overview]部分的聚合:
数组是可以使用语法初始化的聚合(8.5.1)
array<T, N> a = { initializer-list };
其中 initializer-list 是一个逗号分隔的列表,最多包含 N 个元素,其类型可转换为 T。
8.5.1
引用的部分是8.5.1
Aggregates [dcl.init.aggr]并说:
当聚合由初始化列表初始化时,如 8.5.4 中所指定,初始化列表的元素被视为聚合成员的初始化,按递增的下标或成员顺序 [...]
我们又回到了8.5.4
我们开始的部分。