在C++中經常遇到內存的開辟和釋放問題,最近在做項目的時候遇到了一個關于new和delete內存釋放的問題,所以總結下這個問題。在C++ PRimer中,delete一般用來釋放單個對象的內存,delete[]用來釋放多個對象的內存。但是實際的情況比較復雜,特別是涉及到自己定義的類以及類中還有指針內存開辟的問題的時候。以下分三種情況來討論。
一、基本數據類型指針的內存的開辟和釋放。
針對基本數據類型的指針的內存開辟和釋放,delete和delete[]沒有任何區別,都可以實現對內存的釋放。eg:
int* pdata = new int [10]; delete[] pdata; //情況1 pdata = new int [10]; delete pdata; //情況2 pdata = new int; delete pdata; //情況3 pdata = new int; delete[] pdata;//情況4以上四種情況都可以,都可以通過編譯并釋放指針pdata所開辟的內存。
二、自定義的類對象指針的內存和開辟和釋放(類中沒有內存的開辟)。
針對這種情況,delete和delete[]就有了區別??匆韵吕蹋?/p>
類的聲明如下:
class CImage{public: int width; int height; CImage(int w, int h); CImage(); ~CImage();};CImage::CImage(){ cout << "構造函數2被執行" << endl;}CImage::CImage(int w, int h){ width = w; height =h; cout << "構造函數1被執行" << endl;}CImage::~CImage(){ cout << "析構函數被執行" << endl;}主函數如下:{ CImage* pImg = new CImage[10]; delete pImg; //情況1 CImage* pImg = new CImage[10]; delete[] pImg;; //情況2 CImage* pImg = new CImage(3, 4); delete[] pImg; //情況3 CImage* pImg = new CImage(3, 4); delete pImg;//情況4 cout << "通過編譯" << endl; cin.get();}情況1:不能執行成功,類的析構函數就執行一次;情況2:可以執行成功,類的析構函數就執行十次;
情況3:不能執行成功,沒有執行類的析構函數;
·情況4:可以執行成功,類的析構函數就執行一次;
總結:如果是針對自定義的類對象指針的內存和開辟和釋放(類中沒有內存的開辟時),單個對象的內存的開辟必須用delete來釋放,多個對象內存的開辟必須用delete[]來釋放。
三、自定義的類對象指針的內存和開辟和釋放(類中有內存的開辟)。
類的聲明如下:
class CImage{public: int width; int height; CImage(int w, int h); CImage(); ~CImage(); int * pImageData;};CImage::CImage(){ pImageData = NULL; cout << "構造函數2被執行" << endl;}CImage::CImage(int w, int h){ width = w; height =h; pImageData = new int[width*height]; cout << "構造函數1被執行" << endl;}CImage::~CImage(){ if(pImageData != NULL) { cout << "對象內內存被釋放" << endl; delete[] pImageData; pImageData = NULL; } cout << "析構函數被執行" << endl;}主函數如下:{ //情況1 CImage* pImg = new CImage[11]; pImg[0].pImageData = new int [100]; pImg[2].pImageData = new int [100]; delete[] pImg; //情況2 CImage* pImg = new CImage[11]; pImg[0].pImageData = new int [100]; pImg[2].pImageData = new int [100]; delete pImg; //情況3 CImage* pImg = new CImage(3, 4); pImg->pImageData = new int [100]; delete pImg; //情況4 CImage* pImg = new CImage(3, 4); pImg->pImageData = new int [100]; delete[] pImg;}情況1:可以執行,執行了十次構造函數,十次析構函數,同時pImg[0]和pImg[2]對象中pImageData的內存被釋放。情況2:不能執行成功,執行了十次構造函數,一次析構函數,程序停頓。
情況3:可移執行,執行了一次構造函數,一次析構函數,pImg對象中pImageData的內存被釋放。
情況4:不能執行成功,執行了一次構造函數,程序停頓。
總結:如果是針對自定義的類對象指針的內存和開辟和釋放(類中有內存的開辟時),單個對象的內存的開辟必須用delete來
釋放,多個對象內存的開辟必須用delete[]來釋放。注意:這種情況下,delete[]和delete都自動能調用類的析構函數,這樣的話,
在類的析構函數中就需要添加釋放對象中指針開辟內存的代碼。
更近一步:針對下面兩種情況都可以順利執行:
//情況1 CImage* pImg = new CImage(3, 4); pImg->pImageData = new int [100]; delete pImg->pImageData; pImg->pImageData = NULL; delete pImg; //情況2 CImage* pImg = new CImage(3, 4); pImg->pImageData = new int [100]; delete pImg;情況1中,在釋放pImg指針內存之前將其成員指針的內存先釋放,這樣不會有影響;情況2中直接釋放pImg指針內存,這樣,對象的析構函數會自動被調用。但是:在情況2中,如果我們的析構函數中沒有釋放內存的語句,這種情況很容易造成內存泄漏。
新聞熱點
疑難解答
圖片精選