这两种说法有什么区别? 我看不出有什么不同
直到C++14
如果带括号的init-list为空,并且T是具有默认构造函数的类类型,则执行值初始化。 否则,如果T是聚合类型,则执行聚合初始化。
自C++14以来
如果T是聚合类型,则执行聚合初始化。 否则,如果带括号的init-list为空,并且T是具有默认构造函数的类类型,则执行值初始化。
子弹的顺序变了。 我不是想搞笑。 顺序的改变意味着正在进行的初始化类型现在不同了。 当弄清楚初始值设定项的语义时,我们读取每个项目符号并检查其条件。 满足的第一个项目符号决定如何进行初始化。
由于C++14中对聚合类型的修改,顺序发生了更改。 例如,
struct foo {
int a = 1;
int b = 2;
};
在C++11中,foo
不是聚合,但在C++14中它是一个聚合。 因此,当我们写作时
foo f{};
在C++14中,f
应该被聚合初始化,a
变成1,b
在聚合初始化的新语义下变成2。 在C++14中对聚合初始化进行了修改,以允许默认的成员初始值设定项,但要使该措辞生效,初始化必须是聚合初始化。
同样,告诉我们要执行何种类型的初始化以响应各种初始化器的列表也被修改了。
区别在于当两种情况都适用时会发生什么情况:如果T是一个聚合类(而不是数组),它肯定有一个默认构造函数,并且带括号的init-list是空的。 当然,为了理解为什么这很重要,然后我们必须区分值初始化和来自空列表的聚合初始化。
Value initialization 0-初始化对象,然后默认初始化它,对于聚合来说,这是默认初始化它的每个成员,因此Value initialization是按成员进行的(加上清零填充)。 聚合初始化从{}
初始化每个成员,这对于许多类型同样是值初始化,但是对于具有用户提供的默认构造函数的类类型的成员来说是默认初始化。 这一差别可以从以下几个方面看出
struct A {A() {} int i;};
struct B {A a;}; // aggregate
B b{}; // i is 0 in C++11, uninitialized in C++14
B b2=B(); // i is 0 in both versions
仅在C++14中,聚合可以有默认的成员初始值设定项; 当然,这不会导致两种语言版本之间的行为差异,但无论如何,它在这两种规则之间的行为并没有不同(因为它只替换了通用的默认初始化)。
不同的是检查的顺序,所以聚合类型检查是在第一个地方发生的,然后才是其余的。