c++動態內存管理

我們都知道在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;
};

wKiom1baxwziKipDAAAt-y6Xi2g477.png

注意:

new和delete,new[]和delete[]一定要成對出現,在下面我們會解釋爲什麼new[]和delete[]要成對出現。

 

3.new和delete的內部實現:

通過跟蹤調試程序,我們可以知道new和delete內部是通過調用一些函數實現的。

 

new內部是通過調用以下函數實現的

char *  operatoer new(size_t count);

char * operator new[](size_t count);

 

具體調用順序如下:wKiom1ba0yPysAAHAAAb5mp9tP4231.png

delete內部是通過調用以下兩個函數實現的:

void operator delete(char *p);

void operator delete(char *p);

 

具體調用順序如下:

wKioL1ba1mOgp5-zAAAeNXaA7Hg963.png

 

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;

wKioL1ba3Q3TAZmuAAAoB9dGhRk203.png

A* pa=new A[10]開闢內存時傳給operator new[](size_t count)的count是84;

wKioL1ba3cSQb8jhAAApUDDFiws961.png

 

這就說明了new在開闢內置類型的空間時,開闢得空間數量是指定的空間數量,字節數是指定的數量乘以類型的大小。

而在開闢非內置類型空間時,除了開闢指定數量的空間以外,還多開闢4個字節的空間。

new開闢非內置類型的空間時傳給operator new[](size_t count)的count是類型的大小*空間的數量在加上4個字節,最前面的空間裏放的是要執行析構函數的次數。它返回給a2的地址是最前面的空間的後一個空間的地址。

wKioL1ba-V-QvSurAAA2epw540M785.png

 

wKiom1ba9MLRKqlOAAAhGuT0CQ4327.png

 

由於內置類型沒有析構函數,因此沒有多開闢空間。

非內置類型用delete[]在釋放空間時調用operator delete[](char *p),而此時的p被編譯器內部處理過後,它指向的是這些連續空間的最前面一個空間的地址,因此,而傳給operator delete(char *p)的地址是處理過後的地址,因此,他可以釋放一塊連續的空間並且直到調用析構函數的次數。

而如果用delete,則直接調用operator delete(char *p),傳給p的地址是a2的地址,如果釋放它,就相當於釋放動態開闢空間的一部分,這樣會造成內存泄露,使程序崩潰,而編譯器不知道調用多少次析構函數。

 

 

 

 

 

 

 

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