咱們在C++程序中常常看到兩種new的使用方式:new A以及new A()。那麼這兩種究竟有什麼區別呢? 調用new分配的內存有時候會被初始化,而有時候不會,這依賴於A的類型是不是POD(Plain old data)類型,或者它是不是包含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. 注意:VS2008遵循的是98標準,而GCC3.4.5遵循的是03標準。 採用以下代碼能夠驗證編譯器遵循的究竟是哪種標準: #include <stdio.h> #include <string.h> #include <new> struct A { int m; }; // POD struct B { ~B(); int m; }; // non-POD, compiler generated default ctor struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m int main() { char buf[sizeof(B)]; memset( buf, 0x5a, sizeof( buf)); // use placement new on the memset'ed buffer to make sure // if we see a zero result it's due to an explicit // value initialization B* pB = new(buf) B(); //C++98 rules - pB->m is uninitialized //C++03 rules - pB->m is set to 0 printf( "m is %d\n", pB->m); return 0; } 在VS008中輸出就不是0,說明遵循的是98標準。 下面先看一段C++示例代碼: #include <iostream> using namespace std; struct A { int m; }; // POD struct B { ~B(){}; int m; }; // non-POD, compiler generated default ctor struct C { C() : m() {}; ~C(){}; 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; delete aObj1; delete aObj2; delete bObj1; delete bObj2; delete cObj1; delete cObj2; return 0; } 運行結果: 上述測試平臺是VS2008.須要注意的是,VS08只支持C++98。 在這種狀況下: new A:不肯定的值 new A():zero-initialize new B:默認構造(B::m未被初始化) new B():默認構造(B::m未被初始化) new C:默認構造(C::m被zero-initialize) new C():默認構造( C::m被zero-initialize ) 若是用兼容C++03的編譯器,應該產生以下結果: new A:不肯定的值 new A():value-initialize A,因爲是POD類型因此是zero initialization new B:默認構造(B::m未被初始化) new B(): value-initialize B,zero-initialize全部字段,由於使用的默認構造函數 new C:default-initialize C,調用默認構造函數 new C(): value-initialize C,調用默認構造函數 在全部C++版本中,只有當A是POD類型的時候,new A和new A()纔會有區別。並且,C++98和C++03會有區別。 參考資料: What are POD types in C++? What are Aggregates and PODs and how/why are they special?