New運算子詳解
三種new運算子:
new運算子做的三件事:獲得一塊記憶體空間、呼叫建構函式、返回正確的指標
1、new
分配記憶體,呼叫建構函式,定義如下:
void* operator new(std::size_t) throw(std::bad_alloc);
void operator delete(void *) throw();
分配失敗則丟擲異常std::bad_alloc,不是返回NULL,所以判斷返回值是否為NULL是沒用的。
char *p=new char[size]; //分配失敗,不是返回NULL
delete [] p;
2、nothrow new
不丟擲異常。分配失敗時,返回NULL。定義如下:
void* operator new(std::size_t,const std::nothrow_t&) throw();
void operator delete(void*) throw();
char *p=new(nothrow) char[size];//分配失敗,是返回NULL
if(NULL==p)
cout<<"alloc failure!"<<endl;
3、placement new
不會記憶體分配失敗,因為它根本不分配記憶體,只調用物件的建構函式。它允許在一塊已經分配成功的記憶體上重新構造物件或物件陣列。定義如下:
void* operator new(size_t,void*);
void operator delete(void*,void*);
使用placement new構造起來的物件或陣列,要顯式呼叫它們的解構函式來銷燬(解構函式並不釋放物件的記憶體),千萬不要使用delete.這是因為placement new構造起來的物件或陣列大小並不一定等於原來分配的記憶體大小,使用delete會造成記憶體洩漏或者之後釋放記憶體時出現執行時錯誤。
當使用new運算子定義一個多維陣列變數或陣列物件時,它產生一個指向陣列第一個元素的指標,返回的型別保持了除最左邊維數外的所有維數。
New運算子的使用方法:
1、new() :分配這種型別的一個大小的記憶體空間,並以括號中的值來初始化這個變數;
2、 new[] :分配這種型別的n個大小的記憶體空間,並用預設建構函式來初始化這些變數;
char* p=new char[6]; strcpy(p,"Hello");
3、當使用new運算子定義一個多維陣列變數或陣列物件時,它產生一個指向陣列第一個元素的指標,返回的型別保持了除最左邊維數外的所有維數。例如:
int *p1 = new int[10];
返回的是一個指向int的指標int*
int (*p2)[10] = new int[2][10];
new了一個二維陣列, 去掉最左邊那一維[2], 剩下int[10], 所以返回的是一個指向int[10]這種一維陣列的指標int (*)[10].
int (*p3)[2][10] = new int[5][2][10];
new了一個三維陣列, 去掉最左邊那一維[5], 還有int[2][10], 所以返回的是一個指向二維陣列int[2][10]這種型別的指標int (*)[2][10].
4、建立類物件
1)new建立物件,pTest用來接收物件指標。new申請的物件,則只有呼叫到delete時才會執行解構函式,如果程式退出而沒有執行delete則會造成記憶體洩漏:
CTest* pTest = new CTest(); delete pTest;
2)不用new,直接使用類定義申明,使用完後不需要手動釋放,該類解構函式會自動執行:
CTest mTest;
3)使用普通方式建立的類物件,在建立之初就已經分配了記憶體空間。而類指標,如果未經過物件初始化,則不需要delete釋放:
CTest* pTest = NULL;