参见英文答案 >
When can outer braces be omitted in an initializer list?1个
我想知道,为什么在下面的代码中声明std_arr会产生错误,而c_arr编译得很好:
我想知道,为什么在下面的代码中声明std_arr会产生错误,而c_arr编译得很好:
struct S { int a,b; }; S c_arr[] = {{1,2},{3,4}}; // OK std::array<S,2> std_arr = {{1,4}}; // Error: too many initializers
std :: array和S都是聚合.从aggregate initialization on cppreference.com开始:
If the initializer clause is a nested braced-init-list (which is not an expression and has no type),the corresponding class member is
itself an aggregate: aggregate initialization is recursive.
为什么std :: array的初始化不能编译?
解决方法
聚合初始化中的大括号在很大程度上是可选的,因此您可以编写:
S c_arr[] = {1,2,3,4}; // OK std::array<S,2> std_arr = {1,4}; // OK
但是,如果添加大括号,则会使用大括号将其应用于下一个子对象.不幸的是,当你开始嵌套时,这会导致愚蠢的代码有效,而像你这样的合理代码无效.
std::array<S,{2},4}}; // OK
这些都没关系. {1,4}是std_arr的S [2]成员的有效初始化者. {2}没关系,因为它是尝试初始化int,而{2}是一个有效的初始化器. {3,4}被视为S的初始化者,它也是有效的.
std::array<S,4}}; // error
这不合适,因为{1,2}被视为S [2]成员的有效初始化者.剩余的int子对象初始化为零.
然后你有{3,4},但没有更多成员要初始化.
正如评论中指出的那样,
std::array<S,2> std_arr = {{{1,4}}};
也有效.嵌套的{{1,4}}是S [2]成员的初始化者. {1,2}是第一个S元素的初始化. {3,4}是第二个S元素的初始化.
我在这里假设std :: array< S,2>包含S [2]类型的数组成员,它在当前实现中执行,我相信它可能会得到保证,但之前已经涵盖了SO,目前尚未得到保证.