我們都知道在c++中可以用new/malloc動態分配內存空間用delete/free釋放動態開闢的內存空間。
c++中的malloc/free是繼承c語言中的malloc/free,它的用法和在C語言中的用法一模一樣。
1.那麼既然c++中有了可以動態開闢內存的函數爲什麼又要有new/delete呢?
我們知道malloc只是單純的開闢內存空間而不進行初始化,free只是將動態開闢的內存空間給釋放了。
對於內置類型而言,用malloc/free開闢和釋放內存沒有一點問題,但是對於非內置類型來說,由於對象在創建的時候要調用構造函數進行初始化,而在對象在消亡的時候要調用析構函數進行一些清理工作,顯然,malloc/free無法完成這些事情。
因此,c++中提供了new/delete兩個操作符,用new在動態分配內存的時候調用構造函數進行初始化,delete在釋放內存的時候自動調用析構函數進行清理。
2.new/delete的用法
A爲非內置類型
class A { public: A(int a=0,int b=0) :_a(a) ,_b(b) { cout << "A()"<<endl; } ~A() { cout << "~A()" << endl; } private: int _a; };
注意:
new和delete,new[]和delete[]一定要成對出現,在下面我們會解釋爲什麼new[]和delete[]要成對出現。
3.new和delete的內部實現:
通過跟蹤調試程序,我們可以知道new和delete內部是通過調用一些函數實現的。
new內部是通過調用以下函數實現的
char * operatoer new(size_t count);
char * operator new[](size_t count);
delete內部是通過調用以下兩個函數實現的:
void operator delete(char *p);
void operator delete(char *p);
具體調用順序如下:
4.new和delete,new[]和delete[]爲什麼要成對出現?
1.malloc/free爲防止內存泄漏,一定要成對出現。
2.new和delete成對出現的原因則是因爲new開闢內存空間是調用構造函數創建對象,而如果不用delete釋放空間而是用free,那麼釋放空間之前不會執行析構函數,有可能會導致內存泄漏。、
A *pa=new A;
free(pa);//錯誤
delete pa;//正確
3.new[]和delete[]爲什麼要成對出現呢?我們通過執行程序可以發現:
1.當我們用new[]開闢10個連續內置類型空間,而用delete釋放,這時執行程序,程序不會崩潰。
int *p=new int[10];
delete p;
2.當我們用new[]開闢10個連續的非內置類型的空間,沒有用delete[]釋放,執行程序時,程序會崩潰。
A* pa=new A[10];
delete pa;
這是爲什麼呢?
當我們執行下面的程序,
我們發現執行
int *p=new int[10]開闢內存時傳給operator new[](size_t count)的count是40;
A* pa=new A[10]開闢內存時傳給operator new[](size_t count)的count是84;
這就說明了new在開闢內置類型的空間時,開闢得空間數量是指定的空間數量,字節數是指定的數量乘以類型的大小。
而在開闢非內置類型空間時,除了開闢指定數量的空間以外,還多開闢4個字節的空間。
new開闢非內置類型的空間時傳給operator new[](size_t count)的count是類型的大小*空間的數量在加上4個字節,最前面的空間裏放的是要執行析構函數的次數。它返回給a2的地址是最前面的空間的後一個空間的地址。
由於內置類型沒有析構函數,因此沒有多開闢空間。
非內置類型用delete[]在釋放空間時調用operator delete[](char *p),而此時的p被編譯器內部處理過後,它指向的是這些連續空間的最前面一個空間的地址,因此,而傳給operator delete(char *p)的地址是處理過後的地址,因此,他可以釋放一塊連續的空間並且直到調用析構函數的次數。
而如果用delete,則直接調用operator delete(char *p),傳給p的地址是a2的地址,如果釋放它,就相當於釋放動態開闢空間的一部分,這樣會造成內存泄露,使程序崩潰,而編譯器不知道調用多少次析構函數。