这个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;
}
打印出六个预期值。
但如果我将vector<str>
更改为array<str,3>
,gcc会给我这个错误:“std :: array'的初始化程序太多了。”
如果我改变了fields
的初始化:
array<str,3> fields {
str{1,2}, str{3,4}, str{5,6}
};
事情很顺利。
那么为什么我在使用str{1,2}
时需要std::array
,而在使用{1,2}
时只需要std::vector
?
答案 0 :(得分:6)
请参阅aggregate initialization上的cppreference部分。
聚合初始化的影响是:
每个数组元素或非静态类成员,按照类定义中的数组下标/外观的顺序,从中复制初始化 初始化列表的相应子句。
如果initializer子句是嵌套的braced-init-list,则相应的类成员本身就是一个聚合:aggregate 初始化是递归的。
这意味着如果你的结构中有一个聚合,例如:
struct str {
struct asdf
{
int first, last;
} asdf;
};
asdf
将由第一个嵌套的brace-init-list初始化,即{ { 1, 2 } }
。您通常需要两对大括号的原因是因为嵌套的brace-init-list在std::array
中初始化基础聚合(例如,T a[N]
)。
但是,您仍然可以像这样初始化数组:
array<str,3> fields {
1, 2, 3, 4, 5, 6
};
或:
array<str,3> fields { {
1, 2, 3, 4, 5, 6
} };
代替。
另一方面,list initialization涵盖了如何初始化向量。 std::vector
有一个接受std::initializer_list
的构造函数。
类型T对象的列表初始化的效果是:
否则,T的构造函数分为两个阶段:
- 所有构造函数将
的单个参数std::initializer_list
作为唯一参数,或者作为第一个参数,如果其余参数具有 默认值,检查并通过重载决策进行匹配 针对类型std::initializer_list
请注意,您无法初始化矢量(例如:
vector<str> fields {
1,2, 3,4, 5,6
};
但:
vector<int> fields {
1,2, 3,4, 5,6
};
非常好。
答案 1 :(得分:4)
这是因为数组初始化与矢量有点不同 要初始化数组,您需要使用两个大括号 由于语法功能,如果只初始化一个对象,则可以跳过它 所以以下是可以的:
array{1,2,3} -> array{{1,2,3}}
但是在您的示例中,您初始化了多个对象,因此编译器不会添加其他大括号。使用两个括号修复了。
array<str,3> fields {{
{1,2}, {3,4}, {5,6}
}};