C++ new A和new A()的區別詳解

轉自http://blog.csdn.net/xiajun07061225/article/details/8796257

我們在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標準。

採用如下代碼可以驗證編譯器遵循的到底是哪一種標準:

  1. #include <stdio.h>   
  2. #include <string.h>   
  3. #include <new>   
  4.   
  5. struct A { int m; }; // POD   
  6. struct B { ~B(); int m; }; // non-POD, compiler generated default ctor   
  7. struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m   
  8.   
  9. int main()  
  10. {  
  11.     char buf[sizeof(B)];  
  12.     memset( buf, 0x5a, sizeof( buf));  
  13.   
  14.     // use placement new on the memset'ed buffer to make sure    
  15.     //  if we see a zero result it's due to an explicit    
  16.     //  value initialization   
  17.     B* pB = new(buf) B();   //C++98 rules - pB->m is uninitialized   
  18.                             //C++03 rules - pB->m is set to 0   
  19.     printf( "m  is %d\n", pB->m);  
  20.     return 0;  
  21. }  
#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++示例代碼:

  1. #include <iostream>   
  2.   
  3. using namespace std;  
  4.   
  5. struct A { int m; }; // POD   
  6. struct B { ~B(){}; int m; }; // non-POD, compiler generated default ctor   
  7. struct C { C() : m() {}; ~C(){}; int m; }; // non-POD, default-initialising m   
  8.   
  9. int main()  
  10. {  
  11.     A *aObj1 = new A;  
  12.     A *aObj2 = new A();  
  13.     cout << aObj1->m << endl;  
  14.     cout << aObj2->m << endl;  
  15.   
  16.     B *bObj1 = new B;  
  17.     B *bObj2 = new B();  
  18.     cout << bObj1->m << endl;  
  19.     cout << bObj2->m << endl;  
  20.   
  21.     C *cObj1 = new C;  
  22.     C *cObj2 = new C();  
  23.     cout << cObj1->m << endl;  
  24.     cout << cObj2->m << endl;  
  25.   
  26.     delete aObj1;  
  27.     delete aObj2;  
  28.     delete bObj1;  
  29.     delete bObj2;  
  30.     delete cObj1;  
  31.     delete cObj2;  
  32.   
  33.     return 0;  
  34. }  
#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的編譯器,比如G++結果:


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會有區別。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章