在下面的程序中,我试图使用嵌套列表初始化的行初始化我的2x2元素std::array
(当前已注释掉(。MSVC2017给了我一个编译器错误,"初始化程序太多"。为什么?
然后,我尝试了一下非嵌套列表的初始化,这很有效。为什么?
这似乎与嵌套std::vector
的初始化不一致。参见main()
的第三行。请问这里发生了什么事?
#include <array>
#include <iostream>
#include <vector>
int main()
{
//std::array<std::array<int,2>,2> x = {{0,1},{2,3}}; // ERROR: TOO MANY INITIALIZERS
std::array<std::array<int,2>,2> x = {0,1,2,3}; // OK
std::vector<std::vector<int>> y = {{0,1},{2,3}}; // ALSO OK: NOT TOO MANY INITIALIZERS IF A std::vector?
}
在此声明中
std::array<std::array<int,2>,2> x = {{0,1},{2,3}};
您有三个嵌套聚合。括号中包含的第一对值
{0,1}
被编译器认为是作为一个子聚合出现在声明中的第二个聚合的初始值设定项。所以括号中的第二对值
{2,3}
被编译器认为是没有相应对象的冗余。
例如,您可以像一样声明数组
std::array<std::array<int, 2>, 2> x = { { {0,1},{2,3} } };
初始化聚合时,大括号可能会被省略。(C++17标准,11.6.1骨料(
12个大括号可以在初始值设定项列表中删除,如下所示。如果初始值设定项列表以左大括号开头,然后是后面的逗号分隔的初始化器子句列表初始化元素属于亚集合体;有更多是错误的初始化器子句而不是元素。但是,如果初始值设定项列表如果子聚合不是以左大括号开头,那么就足够了列表中的initializer子句用于初始化元素亚集合体的;剩下的任何初始值设定项子句都留给初始化当前亚聚合是一个元素。
所以在这个声明中
std::array<std::array<int,2>,2> x = {0,1,2,3};
大括号被省略,聚合被初始化,如引用中所述。。
在本声明中,
std::vector<std::vector<int>> y = {{0,1},{2,3}};
使用了类std::vector的构造函数,该构造函数接受std::initializer_list作为参数。在这种情况下,构造函数构建的向量元素数量与初始值设定项列表中的元素数量一样多。
std::array
有点特殊。它通常被实现为内置数组的包装器。然后,对于聚合初始化,您需要添加另一对{}
,作为
std::array<std::array<int,2>,2> x = {{{0,1},{2,3}}};
另一方面,std::array<std::array<int,2>,2> x = {0,1,2,3};
由于支架省略而起作用。
If the aggregate initialization uses copy-list-initialization syntax (T a = {args..}), (until C++14)
嵌套初始化器列表周围的大括号可以被省略(省略(,在这种情况下,根据需要使用尽可能多的初始化器子句来初始化相应子集合的每个成员或元素,并且随后的初始化器子句用于初始化对象的以下成员。
如果指定了嵌套的初始值设定项列表,则必须在正确的层中指定初始值设定值列表。对于这种情况,它应该是3层。