原文链接:http://blog.csdn.net/xiajun07061225/article/details/8796257
https://www.zhihu.com/question/36735960?from=profile_question_card
我们在C++程序中经常看到两种new的使用方式:new A以及new A()。
那么这两种究竟有什么区别呢?
我们先了解POD和初始化类型的有关知识。
附:POD类型
POD是Plain old data的缩写,它是一个struct或者类,且不包含构造函数、析构函数以及虚函数。
维基百科给出了更加详细的解释:
C++的POD类型或者是一个标量值,或者是一个POD类型的类。POD class没有用户定义的析构函数、拷贝构造函数和非静态的非POD类型的数据成员。而且,POD class必须是一个aggregate,没有用户定义的构造函数,没有私有的或者保护的非静态数据,没有基类或虚函数。它只是一些字段值的集合,没有使用任何封装以及多态特性。
附:aggregate的定义:
An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
接着介绍一下C++中的三种初始化方式:
zero-initialization,default-initialization,value-initialization。
首先需要注意的是value-initialization是在C++2003标准中新引入的,在原来的1998标准中并不存在。
C++03标准中针对这三种方式的说明:
To zero-initialize an object of type T means:
— if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
— if T is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized;
— if T is a union type, the object’s first named data member is zero-initialized;
— if T is an array type, each element is zero-initialized;
— if T is a reference type, no initialization is performed.
To default-initialize an object of type T means:
— if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is an array type, each element is default-initialized;
— otherwise, the object is zero-initialized.
To value-initialize an object of type T means:
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized
A program that calls for default-initialization or value-initialization of an entity of reference type is ill-formed. If T is a cv-qualified type, the cv-unqualified version of T is used for these definitions of zero-initialization, default-initialization, and value-initialization.
要理解C++(只谈C++11/14之后)的初始化类型,我认为要从最一般类型入手,那就是list initialization,其形式为:
[new] T [object] { arg1, arg2, ... };
list initialization & aggregate initialization
从简单情况来说,list initialization我们并不陌生,本质上就是:
- 如果T是aggregate类型,list中的参数对object成员逐个初始化;或者,
- 如果T不是aggregate类型,编译器查找最匹配list参数的T的构造函数。
而在第一种aggregate initialization情况中,如果list参数个数小于T的成员个数,剩余成员进行value initialization。
value initialization
那么如果在list initialization形式中,没有任何args,也就是
[new] T [object] {};
这时就称为值初始化。这个初始化类型的名字其实有点不明确,按我的理解,实质应该叫做“广义缺省初始化”。因为值初始化一般是三种处理方式:
- 如果T有用户定义的缺省构造函数,直接调用;
- 如果T有编译器生成的缺省构造函数,先0值初始化再调用;
- 如果T根本不是类,直接0值初始化。
而以上三种其实都可以看作缺省初始化。
default initialization
[new] T object;
缺省初始化除了在值初始化过程中可能进行之外,也可以以上面形式单独进行。这种初始化的独特地方在于,如果T是非class类型,则给出非确定值(不赋值),比如:
int i; double d; bool b;
其实这也就是兼容最早的C行为。
zero initialization
0值初始化除了在值初始化过程中可能进行之外,也可以单独作用于静态(或者线程局部)变量:
static T object;
小结
所有其他初始化形式都是list initialization的特殊表现形式或者与其相关。理解的要点在于,list中的参数要么按构造函数的参数声明顺序,要么按aggregate类型成员声明顺序,逐个赋值。当某些成员没有被这样显示给定值时,进行广义缺省初始化(value initialization):或调用缺省构造函数,或赋0值。这么看来,这一堆初始化其实挺符合我们的一贯认知。
五种初始化类型:
list initialization (since C++11)
aggregate initialization 这是list initialization对aggregate类型的特例
value initialization 值初始化
default initialization 缺省初始化
zero initialization 0值初始化
下面看一段C++示例代码:
#include <iostream>
using namespace std;
class A { public:int m; }; // POD
class B { public:~B() {}; int m; }; // non-POD, compiler generated default ctor
class C { public:C() :m() {}; ~C() {}; int m; }; // non-POD, list-initialising m
class D { public:D() {}; ~D() {}; int m; }; // non-POD,default-initialising m
int main()
{
A *aObj1 = new A;
A *aObj2 = new A();
cout << aObj1->m << endl;
cout << aObj2->m << endl;
B *bObj1 = new B;
B *bObj2 = new B();
cout << bObj1->m << endl;
cout << bObj2->m << endl;
C *cObj1 = new C;
C *cObj2 = new C();
cout << cObj1->m << endl;
cout << cObj2->m << endl;
D *dObj1 = new D;
D *dObj2 = new D();
cout << dObj1->m << endl;
cout << dObj2->m << endl;
delete aObj1;
delete aObj2;
delete bObj1;
delete bObj2;
delete cObj1;
delete cObj2;
getchar();
return 0;
}
运行结果:
原文中的初始化类型我个人认为判断不正确,不再复述。
new A:不确定的值
new A():0
new B:不确定的值
new B():0
new C:0
new C():0
new D:不确定的值
new D():不确定的值