delete和delete[ ]的區別點


關於動態申請的內存,分兩種情況:基本數據類型的分配和自定義數據類型的分配。兩者不同。

1、基本數據類型
對於基本數據類型,假如有如下代碼

int *a = new int[10];

...

delete a; // 方式1

delete [ ] a; //方式2

肯定會不少人認為方式1存在內存泄露,然而事實上是不會!針對簡單的基本數據類型,方式1和方式2均可正常工作,因為:基本的數據類型對象沒有析構函數,並且new 在分配內存時會記錄分配的空間大小,則delete時能正確釋放內存,無需調用析構函數釋放其余指針。因此兩種方式均可。

2、自定義數據類型
這里一般指類,假設通過new申請了一個對象數組,注意是對象數組,返回一個指針,對於此對象數組的內存釋放,需要做兩件事情:一是釋放最初申請的那部分空間,二是調用析構函數完成清理工作。對於內存空間的清理,由於申請時記錄了其大小,因此無論使用delete還是delete[ ]都能將這片空間完整釋放,而問題就出在析構函數的調用上,當使用delete時,僅僅調用了對象數組中第一個對象的析構函數,而使用delete [ ]的話,將會逐個調用析構函數。

 

 

 

 有如下代碼:

#include <iostream>;
using namespace std;

class T {
public:
T() { cout << "constructor" << endl; }
~T() { cout << "destructor" << endl; }
};

int main()
{
const int NUM = 3;

T* p1 = new T[NUM];
cout << hex << p1 << endl; //輸出P1的地址
// delete[] p1;
delete p1;

cout << endl;

T* p2 = new T[NUM];
cout << p2 << endl; //輸出P2的地址
delete[] p2;

return 0;
}

大家可以自己運行這個程序,看一看 delete p1 和 delete[] p1 的不同結果,我就不在這里貼運行結果了。


    從運行結果中我們可以看出,delete p1 在回收空間的過程中,只有 p1[0] 這個對象調用了析構函數,其它對象如 p1[1]、p1[2] 等都沒有調用自身的析構函數,這就是問題的症結所在。如果用 delete[],則在回收空間之前所有對象都會首先調用自己的析構函數。
    基本類型的對象沒有析構函數,所以回收基本類型組成的數組空間用 delete 和 delete[] 都是應該可以的;但是對於類對象數組,只能用 delete[]。對於 new 的單個對象,只能用 delete 不能用 delete[] 回收空間。
    所以一個簡單的使用原則就是:new 和 delete、new[] 和 delete[] 對應使用。

————————————————

delete 釋放new分配的單個對象指針指向的內存
delete[] 釋放new分配的對象數組指針指向的內存
那么,按照教科書的理解,我們看下下面的代碼:

int *a = new int[10]; delete a; //方式1 delete [] a; //方式2

肯定會有很多人說方式1肯定存在內存泄漏,是這樣嗎?

下面給出總結性說明:

針對簡單類型

使用new分配后的不管是數組還是非數組形式內存空間用兩種方式均可
如:

int *a = new int[10]; delete a; delete [] a;

此種情況中的釋放效果相同,原因在於:分配簡單類型內存時,內存大小已經確定,系統可以記憶並且進行管理,在析構時,系統並不會調用析構函數,它直接通過指針可以獲取實際分配的內存空間,哪怕是一個數組內存空間
(在分配過程中 系統會記錄分配內存的大小等信息,此信息保存在結構體_CrtMemBlockHeader中具體情況可參看VC安裝目錄CRT\SRC\DBGDEL.cpp)

針對類Class

兩種方式體現出具體差異,當你通過下列方式分配一個類對象數組:

class A
{ private: char *m_cBuffer; int m_nLen; public: A(){ m_cBuffer = new char[m_nLen]; } ~A() { delete [] m_cBuffer; } }; A *a = new A[10];

delete a;
僅釋放了a指針指向的全部內存空間 但是只調用了a[0]對象的析構函數 剩下的從a[1]到a[9]這9個用戶自行分配的m_cBuffer對應內存空間將不能釋放 從而造成內存泄漏

delete [] a;
調用使用類對象的析構函數釋放用戶自己分配內存空間並且 釋放了a指針指向的全部內存空間

總結

對於像int/char/long/int*/struct等簡單數據類型、由於其為基本數據類型沒有析構函數,所以使用delete與delete []相同,兩者都會釋放申請的內存空間,不會有內存泄漏。

當new申請的是C++對象數組時,delete和delete[]差別就很大了,delete只會析構一個對象,而delete[]可以逐一調用數組中的析構函數。

delete ptr 代表用來釋放內存,且只用來釋放ptr指向的內存。
delete[] rg 用來釋放rg指向的內存,還逐一調用數組中每個對象的destructor

建議

為了養成良好的編程習慣,new 和 delete 配套,new[] 和delete[]配套使用。

delete和delete[ ]的區別


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM