std::vector和std::array初始值设定项列表之间的区别
Difference between std::vector and std::array initializer lists
这段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}
};
事情进展顺利。
那么,为什么使用std::array
时需要str{1,2}
,而使用std::vector
时只需要{1,2}
呢?
请参阅cppreference关于聚合初始化的部分。
聚合初始化的影响是:
每个数组元素或非静态类成员,按照类定义中数组下标/出现的顺序,都是从复制初始化的初始值设定项列表的相应子句。
如果初始值设定项子句是嵌套的支撑init列表,那么相应的类成员本身就是一个聚合:聚合初始化是递归的。
这意味着,如果您的结构中有一个聚合,例如:
struct str {
struct asdf
{
int first, last;
} asdf;
};
asdf
将由第一个嵌套的括号初始化列表(即{ { 1, 2 } }
)初始化。通常需要两对大括号的原因是嵌套的大括号init列表初始化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
} };
相反。
另一方面,列表初始化涵盖了如何初始化向量。CCD_ 12具有接受CCD_ 13的构造函数。
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
};
非常好。
这是因为数组初始化的构建与向量有点不同
要初始化数组,需要使用两个大括号
由于语法特性,如果只初始化一个对象,则可以跳过它
所以以下是可以的:
array{1,2,3} -> array{{1,2,3}}
但是在您的示例中,您初始化了多个对象,这样编译器就不会添加额外的大括号。使用两个大括号可以解决这个问题。
array<str,3> fields {{
{1,2}, {3,4}, {5,6}
}};
相关文章:
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 将std ::列表附加到std ::列表的向量中
- STD ::列表对其分配器参数有什么作用
- swig-包装到c#时,没有默认的std ::列表,我该怎么做
- 调用具有std ::列表为参数的C 函数
- STD ::列表和垃圾收集算法
- 低于20亿的质量 - 使用STD ::列表阻碍性能
- C 按其值对object的std ::列表进行排序
- 如何在(C )构造函数参数列表中包含std:列表
- 如何使用迭代器插入std ::列表
- C STD ::列表分割故障
- 将带有指针的 STD 列表复制到另一个带有指针的 STD 列表
- 比较std::对的2个std::列表
- 在 std 列表中查找对象并将其添加到另一个列表
- 与内存堆有关的C 链接列表(STD ::列表)是否使用新的
- 使用STD ::列表作为循环列表安全吗?
- C++当类型T需要构造函数时,是否可以创建类型T的std::列表
- 从对象指针的 STD 列表中擦除对象
- 如何从std::列表中删除项目
- 正在从std::unique_pointer的std::列表中删除元素