我知道以下语句有效
std::vector<int> a{1,2,4} --->A (Aggregate Initialization)
Run Code Online (Sandbox Code Playgroud)
或以下声明
std::vector<int> a;
a = {1,2,4}; ---->B Variable already initialized. - Then aggregate initialization is called
Run Code Online (Sandbox Code Playgroud)
但是对于数组
int c[3]={1,4}; ---->C (1,4,0)
Run Code Online (Sandbox Code Playgroud)
但以下行为是不允许的
int c[3];
c = {1,4}; ---->D
Run Code Online (Sandbox Code Playgroud)
现在我的问题是为什么 B 有效而 D 无效?
\n\n\nRun Code Online (Sandbox Code Playgroud)\nstd::vector<int> a{1,2,4};\n
这是初始化器列表初始化,而不是聚合,因为vector不是聚合 \xe2\x80\x94 它的数据存储在堆上。您需要让它#include <initializer_list>工作,尽管该标头通常包含在<vector>.
\n\n\nRun Code Online (Sandbox Code Playgroud)\na = {1,2,4};\n
这也经历了一个在 上重载的函数std::initializer_list,语义与函数调用相同:
a.assign( {1,2,4} );\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\nRun Code Online (Sandbox Code Playgroud)\nint c[3]={1,4};\n
这是聚合初始化。但是,您不能c = { 3, 5, 6 }在之后执行此操作,因为花括号初始化列表可能只是新变量的初始值设定项,而不是内置表达式的操作数。(在声明中,符号=只是初始化的符号。它不是通常的运算符。赋值运算符的语法特别允许花括号列表,但这种用法仅在函数重载时有效,这会导致列表初始化一个新变量:函数参数。)
最后一个问题的答案是,无法operator =为“裸”数组编写必要的重载,因为它必须是成员函数。解决方法是使用std::copyand 一个std::initializer_list对象。
正如其他答案中所解释的,此赋值的机制是向量的std::initializer_list赋值运算符。这使得使用大括号括起来的任意值的初始值设定项列表成为可能,尽管std::vector<int>不是聚合:
std::vector<int> a;
a = {1,2,4}; // OK, vector& operator=(std::initializer_list<T>)
Run Code Online (Sandbox Code Playgroud)
但以下行为是不允许的
int c[3];
c = {1,4}; // Error: arrays are not assignable
Run Code Online (Sandbox Code Playgroud)
这是因为数组不可分配。如果它是一种不同类型的聚合,那么这就会起作用。例如,
struct Foo { int a, b, c; }; // aggregate
Foo f = {1, 2, 3}; // OK, aggregate initialization
f = { 1, 4 }; // OK
Run Code Online (Sandbox Code Playgroud)
这里,f.a、f.b和分别f.c被赋值1, 4, 0。
此外,当非聚合具有带有与列表元素explicit兼容的参数列表的(非)构造函数时,也可以使用大括号括起来的初始值设定项列表来初始化和分配非聚合。例如,
struct Bar
{
Bar(int a, int b, int c) : a(a), b(b), c(c) {} // non-aggregate
int a, b, c;
};
Bar b0 = {1, 2, 3}; // OK
Bar b1 = {1,2}; // Error: number of elements must be 3
b0 = {11, 22, 33}. // Assignemnt OK
Run Code Online (Sandbox Code Playgroud)