简而言之,有时候new运算符返回的内存将被初始化,有时候不会,这取决于您要新建的类型是否为POD(旧式数据),或者它是否是包含POD成员并使用编译器生成的默认构造函数的类。
- C++1998有两种初始化类型:零初始化和默认初始化
- C++2003添加了第三种初始化类型,值初始化
- C++2011/C++2014只添加了列表初始化,并且值/默认/零初始化的规则有所改变。
假设:
struct A { int m; };
struct B { ~B(); int m; };
struct C { C() : m(){}; ~C(); int m; };
struct D { D(){}; int m; };
struct E { E() = default; int m;}; /** only possible in c++11/14 */
struct F {F(); int m;}; F::F() = default; /** only possible in c++11/14 */
在C++98编译器中,应该出现以下情况:
new A
- 不确定的值(A
是POD)new A()
- 零初始化new B
- 默认构造(B::m
未初始化,B
是非POD类型)new B()
- 默认构造(B::m
未初始化)new C
- 默认构造(C::m
零初始化,C
是非POD类型)new C()
- 默认构造(C::m
零初始化)new D
- 默认构造(D::m
未初始化,D
是非POD类型)new D()
- 默认构造?(D::m
未初始化)
new A
- 不确定的值 (A
是 POD)new A()
- 值初始化A
,因为它是一个 POD,所以它是零初始化。new B
- 默认初始化(B::m
未初始化,B
是非 POD)new B()
- 值初始化B
,因为它的默认构造函数是编译器生成的而不是用户定义的,所以所有字段都被零初始化。new C
- 默认初始化C
,调用默认构造函数。(C::m
被零初始化,C
是非 POD)new C()
- 值初始化C
,调用默认构造函数。(C::m
被零初始化)new D
- 默认构造(D::m
未初始化,D
是非 POD)new D()
- 值初始化 D?,调用默认构造函数(D::m
未初始化)
在符合C++11标准的编译器中,应该按照以下方式工作:
??? (如果我从这里开始,无论如何都会出错,请帮忙)
在符合C++14标准的编译器中,应该按照以下方式工作:
??? (如果我从这里开始,无论如何都会出错,请帮忙) (基于答案的草稿)
new A
- 默认初始化A
,编译器生成构造函数,(A::m
未初始化)(A
是POD)new A()
- 值初始化A
,由于第2点在/8中,因此它是零初始化new B
- 默认初始化B
,编译器生成构造函数,(B::m
未初始化)(B
是非POD)new B()
- 值初始化B
,由于其默认构造函数是编译器生成的而不是用户定义的,因此会将所有字段都进行零初始化。new C
- 默认初始化C
,调用默认构造函数。 (C::m
为零初始化,C
是非POD)new C()
- 值初始化C
,调用默认构造函数。 (C::m
为零初始化)new D
- 默认初始化D
(D::m
未初始化,D
是非POD)new D()
- 值初始化D
,调用默认构造函数(D::m
未初始化)new E
- 默认初始化E
,调用编译器生成的构造函数。(E::m
未初始化,E是非POD)new E()
- 值初始化E
,由于/8中的第2点,会将E
进行零初始化。new F
- 默认初始化F
,调用编译器生成的构造函数。(F::m
未初始化,F
是非POD)new F()
- 值初始化F
,由于/8中的第1点,F
构造函数如果在其第一次声明中是用户提供的且未明确默认化或删除,则为用户提供。(Link)
struct D { D() {}; int m; };
可能值得包含在你的列表中。 - Yakk - Adam Nevraumont