delete 和 delete [] 的真正區(qū)別
掃描二維碼
隨時隨地手機看文章
來源:cbNotes
鏈接:http://blog.csdn.net/cbnotes/article/details/38900799
c++ 中對new
申請的內(nèi)存的釋放方式有 delete
和 delete[]
兩種方式,到底這兩者有什么區(qū)別呢?
我們通常從教科書上看到這樣的說明:
-
delete 釋放new分配的單個對象指針指向的內(nèi)存 -
delete[] 釋放new分配的對象數(shù)組指針指向的內(nèi)存
那么,按照教科書的理解,我們看下下面的代碼:
int *a = new int[10];
delete a; //方式1
delete[] a; //方式2
1. 針對簡單類型 使用new分配后的不管是數(shù)組還是非數(shù)組形式內(nèi)存空間用兩種方式均可 如:
int *a = new int[10];
delete a;
delete[] a;
此種情況中的釋放效果相同,原因在于:分配簡單類型內(nèi)存時,內(nèi)存大小已經(jīng)確定,系統(tǒng)可以記憶并且進行管理,在析構(gòu)時,系統(tǒng)并不會調(diào)用析構(gòu)函數(shù)。
它直接通過指針可以獲取實際分配的內(nèi)存空間,哪怕是一個數(shù)組內(nèi)存空間(在分配過程中 系統(tǒng)會記錄分配內(nèi)存的大小等信息,此信息保存在結(jié)構(gòu)體 _CrtMemBlockHeader 中,具體情況可參看 VC 安裝目錄下 CRTSRCDBGDEL.cpp)。
2. 針對類Class,兩種方式體現(xiàn)出具體差異
當你通過下列方式分配一個類對象數(shù)組:
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指針指向的全部內(nèi)存空間 但是只調(diào)用了a[0]對象的析構(gòu)函數(shù) 剩下的從a[1]到a[9]這9個用戶自行分配的m_cBuffer對應(yīng)內(nèi)存空間將不能釋放 從而造成內(nèi)存泄漏
delete[] a; //調(diào)用使用類對象的析構(gòu)函數(shù)釋放用戶自己分配內(nèi)存空間并且 釋放了a指針指向的全部內(nèi)存空間
所以總結(jié)下就是,如果 ptr
代表一個用new申請的內(nèi)存返回的內(nèi)存空間地址,即所謂的指針,那么:
delete ptr
代表用來釋放內(nèi)存,且只用來釋放 ptr
指向的內(nèi)存。delete[] rg
用來釋放rg
指向的內(nèi)存,??!還逐一調(diào)用數(shù)組中每個對象的destructor
??!
對于像int/char/long/int*/struct
等等簡單數(shù)據(jù)類型,由于對象沒有 destructor ,所以用 delete
和 delete []
是一樣的!但是如果是 C++ 對象數(shù)組就不同了!
關(guān)于 new[]
和 delete[]
,其中又分為兩種情況:
-
(1)為基本數(shù)據(jù)類型分配和回收空間; -
(2)為自定義類型分配和回收空間;
對于 (1),上面提供的程序已經(jīng)證明了delete[]
和delete
是等同的。但是對于 (2),情況就發(fā)生了變化。
我們來看下面的例子,通過例子的學習了解 C++ 中的 delete
和 delete[]
的使用方法
#include <iostream>
using namespace std;
class Babe
{
public:
Babe()
{
cout << \"Create a Babe to talk with me\" << endl;
}
~Babe()
{
cout << \"Babe don\'t Go away,listen to me\" << endl;
}
};
int main()
{
Babe* pbabe = new Babe[3];
delete pbabe;
pbabe = new Babe[3];
delete[] pbabe;
return 0;
}
結(jié)果是:
Create a babe to talk with me
Create a babe to talk with me
Create a babe to talk with me
Babe don\'t go away,listen to me
Create a babe to talk with me
Create a babe to talk with me
Create a babe to talk with me
Babe don\'t go away,listen to me
Babe don\'t go away,listen to me
Babe don\'t go away,listen to me
大家都看到了,只使用 delete
的時候只出現(xiàn)一個 Babe don’t go away,listen to me
,而使用 delete[]
的時候出現(xiàn) 3 個 Babe don’t go away,listen to me
。不過不管使用 delete
還是 delete[]
那三個對象的在內(nèi)存中都被刪除,既存儲位置都標記為可寫,但是使用 delete
的時候只調(diào)用了 pbabe[0]
的析構(gòu)函數(shù),而使用了 delete[]
則調(diào)用了 3 個 Babe
對象的析構(gòu)函數(shù)。
你一定會問,反正不管怎樣都是把存儲空間釋放了,有什么區(qū)別。
答:關(guān)鍵在于調(diào)用析構(gòu)函數(shù)上。此程序的類沒有使用操作系統(tǒng)的系統(tǒng)資源(比如:Socket、File、Thread
等),所以不會造成明顯惡果。如果你的類使用了操作系統(tǒng)資源,單純把類的對象從內(nèi)存中刪除是不妥當?shù)?,因為沒有調(diào)用對象的析構(gòu)函數(shù)會導致系統(tǒng)資源不被釋放,如果是 Socket 則會造成 Socket 資源不被釋放,最明顯的就是端口號不被釋放,系統(tǒng)最大的端口號是 65535 (216 _ 1,因為還有0),如果端口號被占用了,你就不能上網(wǎng)了,呵呵。如果 File 資源不被釋放,你就永遠不能修改這個文件,甚至不能讀這個文件(除非注銷或重啟系統(tǒng))。如果線程不被釋放,這它總在后臺運行,浪費內(nèi)存和 CPU 資源。這些資源的釋放必須依靠這些類的析構(gòu)函數(shù)。所以,在用這些類生成對象數(shù)組的時候,用 delete[]
來釋放它們才是王道。而用 delete
來釋放也許不會出問題,也許后果很嚴重,具體要看類的代碼了。
免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!