日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

delete p和delete[] p的區(qū)別

 quandsu 2013-04-19

今天在愛立信南京研發(fā)中心筆試碰到一個(gè)簡答題為:delete p和delete[] p的區(qū)別,答的不好,下面從網(wǎng)上拷貝一篇文章,來具體說明。

operator new 和 operator delete函數(shù)有兩個(gè)重載版本,每個(gè)版本支持相關(guān)的new表達(dá)式和delete表達(dá)式:

void* operator new (size_t);        // allocate an object
void* operator new [] (size_t); // allocate an array

void operator delete (void*); // free an oject
void operator delete [] (void*); // free an array
熟悉C的朋友看到這里可能會(huì)很奇怪:
在c中釋放內(nèi)存用free(void *)【注意這里只有一個(gè)參數(shù)void *】
為什么到了C++里會(huì)出現(xiàn)兩個(gè)!按理說delete 會(huì)調(diào)用free釋放內(nèi)存的?。?br>另外delete []是如何知道刪除的對(duì)象個(gè)數(shù)的?

另外一般的教材比如《高質(zhì)量C++編程指南》都會(huì)這么說:
在用delete 釋放對(duì)象數(shù)組時(shí),留意不要丟了符號(hào)‘[]’。例如
delete []objects; // 正確的用法
delete objects; // 錯(cuò)誤的用法
后者相當(dāng)于delete objects[0],漏掉了另外99 個(gè)對(duì)象
這樣的描述當(dāng)然是錯(cuò)誤的,而且會(huì)誤導(dǎo)觀眾

為了解決問題,打開vc6,輸入以下代碼:
復(fù)制代碼
class A
{
private:
int i;
string s;
public:
~A() { printf("hi"); }
};
void d(A *);
int main(int argc, char* argv[])
{
A *p = new A[10];
d(p);
return 0;
}

void d(A *p)
{
delete p;
}
復(fù)制代碼
運(yùn)行結(jié)果:debug assertion failed!
咦,不是說等同于delete p[0]嗎?

為了看看究竟,只好動(dòng)用那多年以前就忘光了的匯編
經(jīng)過一番折騰,最后連猜帶蒙得出下面的觀點(diǎn):
1 如果對(duì)象無析構(gòu)函數(shù)(包括不需要合成析構(gòu)函數(shù),比如注釋掉~A和string s兩行代碼)
delete會(huì)直接調(diào)用operator delete并直接調(diào)用free釋放內(nèi)存
這個(gè)時(shí)候的new=new [](僅在數(shù)量上有差異),delete=delete[]
2 如果對(duì)象存在析構(gòu)函數(shù)(包括合成析構(gòu)函數(shù)),則【這個(gè)才是重點(diǎn)】:
new []返回的地址會(huì)后移4個(gè)字節(jié),并用那4個(gè)存放數(shù)組的大小!而new不用后移這四個(gè)字節(jié)
delete[]根據(jù)那個(gè)4個(gè)字節(jié)的值,調(diào)用指定次數(shù)的析構(gòu)函數(shù) ,同樣delete也不需要那四個(gè)字節(jié)
結(jié)果就是在不恰當(dāng)?shù)氖褂胐elete 和delete []調(diào)用free的時(shí)候會(huì)造成4個(gè)字節(jié)的錯(cuò)位,最終導(dǎo)致debug assertion failed!
再回到《高質(zhì)量C++編程指南》:
delete []objects; // 正確的用法
delete objects; // 錯(cuò)誤的用法
后者相當(dāng)于delete objects[0],漏掉了另外99 個(gè)對(duì)象
嚴(yán)格應(yīng)該這樣說:后者相當(dāng)于僅調(diào)用了objects[0]的析構(gòu)函數(shù),漏掉了調(diào)用另外99 個(gè)對(duì)象的析構(gòu)函數(shù),并且在調(diào)用之后釋放內(nèi)存時(shí)導(dǎo)致異常(如果存在析構(gòu)函數(shù)的話),如果對(duì)象無析構(gòu)函數(shù)該語句與delete []objects相同

注:
1 測(cè)試環(huán)境vc6
2 不保證觀點(diǎn)正確
3 歡迎指正

由new分配的一個(gè)數(shù)組空間,比如說 int *array=new int[50],當(dāng)用delete釋放這個(gè)空間時(shí),用語句delete []array和delete array是否等價(jià)!

C++告訴我們?cè)诨厥沼?new 分配的單個(gè)對(duì)象的內(nèi)存空間的時(shí)候用 delete,回收用 new[] 分配的一組對(duì)象的內(nèi)存空間的時(shí)候用 delete[]。

關(guān)于 new[] 和 delete[],其中又分為兩種情況:(1) 為基本數(shù)據(jù)類型分配和回收空間;(2) 為自定義類型分配和回收空間。

對(duì)于 (1),上面提供的程序a可以證明了 delete[] 和 delete 是等同的。
程序a:

復(fù)制代碼
#include <stdio.h> 
#define BUFF_SIZE 10240
int main(int argc, char *argv[])
{
printf("Hello, world\n");
char* p = NULL;
while(1)
{
p = new TTT[BUFF_SIZE];
printf("0x%08XH\n",p);
Sleep(5000);
delete p; //或者delete [] p;
p = NULL;
}
return 0;
}
復(fù)制代碼

但是對(duì)于 (2),情況就發(fā)生了變化。請(qǐng)看下面的程序。

復(fù)制代碼
#include <stdio.h> 
#define BUFF_SIZE 10240

class TTT
{
public:
TTT()
{
//aa = new char[1024];
};
~TTT()
{
//delete [] aa;
//printf("TTT destructor()\n");
};
private:
int a;
char* aa;
int inta[1024];
};

int main(int argc, char *argv[])
{
printf("Hello, world\n");
TTT* p = NULL;
while(1)
{
p = new TTT[BUFF_SIZE];
printf("0x%08XH\n",p);
delete p; //delete [] p;
p = NULL;
}
return 0;
}
復(fù)制代碼


大家可以自己運(yùn)行這個(gè)程序,看一看 delete p1 和 delete[] p1 的不同結(jié)果,我就不在這里貼運(yùn)行結(jié)果了。

從運(yùn)行結(jié)果中我們可以看出,delete p 在回收空間的過程中,只有 p[0] 這個(gè)對(duì)象調(diào)用了析構(gòu)函數(shù),其它對(duì)象如 p[1]、p[2] 等都沒有調(diào)用自身的析構(gòu)函數(shù),在析構(gòu)函數(shù)中的內(nèi)存釋放操作將不會(huì)被執(zhí)行(引發(fā)內(nèi)存泄漏),已使用內(nèi)存不斷增加,這就是問題的癥結(jié)所在。如果用 delete[],則在回收空間之前所有對(duì)象都會(huì)首先調(diào)用自己的析構(gòu)函數(shù),已使用內(nèi)存不會(huì)不斷增加。

基本類型的對(duì)象沒有析構(gòu)函數(shù),所以回收基本類型組成的數(shù)組空間用 delete 和 delete[] 都是應(yīng)該可以的;但是對(duì)于類對(duì)象數(shù)組,只能用 delete[]。對(duì)于 new 的單個(gè)對(duì)象,只能用 delete 不能用 delete[] 回收空間。

測(cè)了一下,好像沒有區(qū)別,又想不起在什么地方能用到delete[],大家評(píng)論一下。

復(fù)制代碼
#include <iostream>; 
#include "xercesc/dom/DOM.hpp"
int main(){

char* pc = 0;
char* pc2;
int i = 21;
pc = new char;
std::cout<<(long)pc<<std::endl;
delete pc;
std::cout<<(long)pc<<std::endl;

pc2 = new char;
std::cout<<(long)pc2<<std::endl;

return 0;
}
復(fù)制代碼

輸出:
[root@ts xml]# ./a.out
134519536
134519536
134519536
地址沒有變化,用delete[], delete都一樣


所以一個(gè)簡單的使用原則就是:new 和 delete、new[] 和 delete[] 對(duì)應(yīng)使用。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多