std :: array的嵌套聚合初始化

Mik*_*ail 7 c++ arrays initialization aggregate-initialization c++14

我想知道,为什么std_arr在下面的代码中声明会产生错误,同时c_arr编译得很好:

struct S { int a, b; };

S c_arr[] = {{1, 2}, {3, 4}};  // OK
std::array<S, 2> std_arr = {{1, 2}, {3, 4}};  // Error: too many initializers
Run Code Online (Sandbox Code Playgroud)

双方std::arrayS都聚集.从cppreference.com上的聚合初始化:

如果initializer子句是嵌套的braced-init-list(它不是表达式且没有类型),则相应的类成员本身就是一个聚合:聚合初始化是递归的.

为什么这个初始化std::array不能编译?

小智 8

聚合初始化中的大括号在很大程度上是可选的,因此您可以编写:

S c_arr[] = {1, 2, 3, 4};  // OK
std::array<S, 2> std_arr = {1, 2, 3, 4};  // OK
Run Code Online (Sandbox Code Playgroud)

但是,如果添加大括号,则会使用大括号将其应用于下一个子对象.不幸的是,当你开始嵌套时,这会导致愚蠢的代码有效,而像你这样的敏感代码无效.

std::array<S, 2> std_arr = {{1, 2, 3, 4}};  // OK
std::array<S, 2> std_arr = {1, 2, {3, 4}};  // OK
std::array<S, 2> std_arr = {1, {2}, {3, 4}};  // OK
Run Code Online (Sandbox Code Playgroud)

这些都没关系.{1, 2, 3, 4}是该S[2]成员的有效初始化者std_arr.{2}没关系,因为它是尝试初始化一个int,并且{2}是一个有效的初始化器.{3, 4}被视为初始化者S,并且对此也有效.

std::array<S, 2> std_arr = {{1, 2}, {3, 4}};  // error
Run Code Online (Sandbox Code Playgroud)

这不合适,因为{1, 2}它被视为S[2]成员的有效初始化者.剩余的int子对象初始化为零.

然后你有{3, 4},但没有更多成员初始化.

正如评论中指出的那样,

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

也有效.嵌套{{1, 2}, {3, 4}}S[2]成员的初始化者.这{1, 2}是第一个S元素的初始化者.这{3, 4}是第二个S元素的初始化.

我假设这里std::array<S, 2>包含一个类型的数组成员S[2],它在当前的实现上执行,并且我相信它可能会得到保证,但之前已经涵盖了SO,目前还没有保证.