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