C++ std::vector和std::array初始值设定项列表之间的差异

C++ std::vector和std::array初始值设定项列表之间的差异,c++,arrays,c++11,stdvector,initializer-list,C++,Arrays,C++11,Stdvector,Initializer List,这段C++11代码对我来说很好: #include <iostream> #include <vector> #include <array> using namespace std; struct str { int first, last; }; vector<str> fields { {1,2}, {3,4}, {5,6} }; int main() { for (str s : fields)

这段C++11代码对我来说很好:

#include <iostream>
#include <vector>
#include <array>
using namespace std;

struct str {
    int first, last;
};


vector<str> fields {
    {1,2}, {3,4}, {5,6}
};

int main()
{
    for (str s : fields)
        cout << s.first << " " << s.last << endl;
}
事情进展顺利


那么,为什么我在使用
std::array
时需要
str{1,2}
,而在使用
std::vector
时只需要
{1,2}

这是因为数组初始化与vector构建的有点不同。
要初始化数组,需要使用两个大括号。
由于语法功能,如果只初始化一个对象,则可以跳过它。
因此,以下是确定的:

array{1,2,3} -> array{{1,2,3}}
但在您的示例中,您初始化了多个对象,因此编译器不会添加额外的大括号。使用两个大括号修复了这个问题

array<str,3> fields {{
    {1,2}, {3,4}, {5,6}
}};
数组字段{{
{1,2}, {3,4}, {5,6}
}};

请参见cppreference的部分

聚合初始化的效果如下:

  • 每个数组元素或非静态类成员,按照类定义中数组下标/外观的顺序,都是从中复制初始化的 初始值设定项列表的相应子句

  • 如果initializer子句是嵌套的大括号init列表,则相应的类成员本身就是一个aggregate:aggregate 初始化是递归的

这意味着如果在结构中有一个聚合,例如:

struct str {
    struct asdf
    {
        int first, last;
    } asdf; 
};
asdf
将由第一个嵌套的brace init列表初始化,即
{{{1,2}
。通常需要两对大括号的原因是嵌套的大括号初始化列表初始化了
std::array
中的底层聚合(例如,
ta[N]

但是,您仍然可以如下方式初始化阵列:

array<str,3> fields {
    1, 2, 3, 4, 5, 6
};
vector<str> fields {
    1,2, 3,4, 5,6
};
但是:

向量场{
1,2, 3,4, 5,6
};
很好

array<str,3> fields { {
    1, 2, 3, 4, 5, 6
} };
vector<str> fields {
    1,2, 3,4, 5,6
};
vector<int> fields {
    1,2, 3,4, 5,6
};