C ++ 11标准的第8.5p7段规定:
对T类型的对象进行值初始化意味着:
如果T是具有用户提供的构造函数的(可能是cv限定的)类类型(第9节) (12.1),然后调用T的默认构造函数(和 如果T没有可访问的默认值,则初始化是错误的 构造函数);
如果T是(可能是cv限定的)非联合类类型 没有用户提供的构造函数,那么对象就是 零初始化,如果T是隐式声明的默认构造函数 是非平凡的,那个构造函数被调用。
如果T是数组类型, 然后每个元素都是值初始化的;
否则,对象是 初始化为零。
我在理解上面粗体字符时遇到问题。额外调用T的隐式默认构造函数如何改变零初始化,这种情况刚刚发生?
答案 0 :(得分:16)
这是一个具体的例子:
class A {
int a;
public:
A() : a(1) {}
};
class B {
int b;
A c;
};
B
属于此类别 - 它是一个非联合类类型,没有用户提供的构造函数。因此,如果B
是值初始化的,它将首先进行零初始化(因此b
和c.a
都将设置为0),然后将调用默认构造函数(这将调用A
的构造函数并将c.a
设置为1)。
根据as-if
规则,优化程序可以将这些组合成一个步骤(将b
设置为0,将c.a
设置为1),因为没有人可以查看零初始化和默认构造函数之间的对象。
答案 1 :(得分:5)
T
可能没有自己的显式默认构造函数,但它可能来自U
,它可以和/或具有类型V
的成员。
答案 2 :(得分:4)
struct S {
int a, b;
S() : b(10) {}
};
struct T {
S s;
};
int main() {
S s{};
T t{};
}
t
已初始化值,T
没有用户提供的构造函数。但是T
隐式声明的默认构造函数并不简单。
s
也是初始值,但S
有一个用户提供的构造函数。
s.a
将具有不确定的价值。但由于在默认构造函数调用之前的零初始化,t.s.a
为零。 s.b
和t.s.b
都设置为值10。