亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

對象析構(gòu)談—— delete this 的使用及注意事項

系統(tǒng) 1744 0

對象析構(gòu)談—— delete this 的使用及注意事項 (轉(zhuǎn)自: http://blog.csdn.net/weiqubo/article/details/4746969

In order to understand "delete this" :

First Step - dive into "delete p "

delete p 執(zhí)行了哪些步驟?
delete p 是一個兩步的過程:調(diào)用析構(gòu)函數(shù)(釋放類里邊涉及new的內(nèi)存),然后釋放內(nèi)存(類本身占的內(nèi)存)。

delete p產(chǎn)生的代碼看上去是這樣的(假設(shè)是Object*類型的):

delete原語可以看作如下這樣一個過程:
p->~Object();
p->operator delete(p);

p->~Object() 語句調(diào)用p指向的Object對象的析構(gòu)函數(shù)。
p->operator delete(p) 語句調(diào)用對象p的內(nèi)存釋放原語 void operator delete(void* p)。如果沒有實現(xiàn)該方法,將調(diào)用系統(tǒng)的內(nèi)存釋放原語::operator delete(ptr)做釋放該對象內(nèi)存的操作。 當然細節(jié)上并不這么簡單,我們最后的實驗部分會詳細討論

Second Step - "delete this"

成員函數(shù)調(diào)用delete this合法嗎?
只要你小心,一個對象請求自殺 (delete this) 是可以的。

以下是我對“小心”的定義:

你必須100%的確定,this對象是用 new分配的(不是用new[],也不是用定位放置 new,也不是一個棧上的局部對象,也不是全局的,也不是另一個對象的成員,而是明白的普通的new)。

你必須100%的確定,該成員函數(shù)是this對象最后調(diào)用的的成員函數(shù)。

你必須100%的確定,剩下的成員函數(shù)(delete this之后的)不接觸到this對象任何一塊(包括調(diào)用任何其他成員函數(shù)或訪問任何數(shù)據(jù)成員)。

你必須100%的確定,在delete this之后不再去訪問this指針。換句話說,你不能去檢查它,將它和其他指針比較,和NULL比較,打印它,轉(zhuǎn)換它,對它做任何事。

自然,對于這種情況還要習慣性地告誡:當你的指針是一個指向基類類型的指針,而沒有虛析構(gòu)函數(shù)時(也不可以delete this)。

注意:因為是在類成員函數(shù)里面delete this的,所以在此語句以后,不能訪問任何的成員變量及 函數(shù)(調(diào)用虛函數(shù)必須對象實例存在以檢查類型),否則一定非法。

上面所說的在執(zhí)行時不一定會報錯,但盡量不要這么做。

Some test examples:

析構(gòu)函數(shù)本身是不會釋放內(nèi)存的,
除非在析構(gòu)函數(shù)里面顯示的使用delete操作符.
在對類指針使用delete時,實際發(fā)生了兩個步驟。
A:先是調(diào)用該類的析構(gòu)函數(shù),以做數(shù)據(jù)成員的釋放工作,以及一些finish code,這一切由程序員自己定義。
B:然后再調(diào)用operator delete(void*)釋放該對象實例的內(nèi)存數(shù)據(jù)。這是一個對象在消亡之前的所做的最后動作。 一般不要 override這個函數(shù),如果要,務(wù)必記住最后調(diào)用系統(tǒng)的::operator delete真正釋放該對象所占用的內(nèi)存
一般來說,內(nèi)存釋放釋放的只能是數(shù)據(jù)段的內(nèi)容(包括堆和棧,但釋放棧上的內(nèi)存由系統(tǒng)進行),而代碼段的內(nèi)存,除一些病毒攻擊等非正常強行改寫手段外,在內(nèi)存中是永遠不會釋放/改變的,直到程序結(jié)束,因此在內(nèi)存釋放后也是可以訪問的。 所以,一般所謂的釋放內(nèi)存 delete操作,是在數(shù)據(jù)段進行的釋放
可以試試下面的代碼
Example 1: 兩步操作
class x {
public :
??????? x(){}
??????? ~x() {
??????????????? printf("%s/n","~x()");
??????? }
};
void main() {
??????? x* p=new x;
??????? ::operator delete(p); //調(diào)用delete內(nèi)存釋放原語,不會調(diào)用~x(),如果確實調(diào)用了系統(tǒng)::operator delete,就沒有內(nèi)存泄露(也可能由用戶函數(shù)覆蓋)
??????? delete p; //~x()依然會執(zhí)行,operator delete中將會報錯(最后將討論)
}
Example 2: override 重寫的operator delete
class x {
public :
??????? x(){
??????? }
??????? ~x() {
??????????????? printf("~x()/n");
??????????????? //delete p; //這里若進行此操作則會陷入嵌套
??????? }
??????? void operator delete(void * ptr) {
??????????????? printf("x::delete()/n");
??????? }
};
void main() {
??????? x* p=new x;
??????? delete p; //依次調(diào)用p的~x()和operator delete
??????? delete p; //不會報錯,因為"operator delete" override了系統(tǒng)函數(shù),沒有進行::operator delete(this)操作。
??????? delete p; //同理依然不會報錯
}
Example 3: 默認的operator delete
class x {
public :
??????? x(){
??????????????? //delete p; //構(gòu)造時delete不會報錯,只要確保以后不會用到該實例(包括delete p)。
??????? }
??????? ~x() {
??????????????? printf("~x()/n");
??????? }
};

void main() {
??????? x* p=new x;
??????? delete p; //依次調(diào)用p的~x()和operator delete(其中調(diào)用了系統(tǒng)的::operator delete)
??????? //delete p; //報錯,這里沒有override,對象調(diào)用的是系統(tǒng)的::operator delete
}

進一步分析:
讓我們看一下系統(tǒng)::operator delete的內(nèi)部實現(xiàn)(in dbgdel.cpp):
void operator delete(
??????? void *pUserData
??????? )
{
??????? _CrtMemBlockHeader * pHead;

??????? RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));

??????? if (pUserData == NULL)
??????????? return;

??????? _mlock(_HEAP_LOCK); /* block other threads */
??????? __TRY

/* get a pointer to memory block header */
??????????? pHead = pHdr(pUserData);

/* verify block type */
??????????? _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)); //檢查該段內(nèi)存是否被程序占用。一般出現(xiàn)的如果內(nèi)存已經(jīng)釋放了,又執(zhí)行內(nèi)存釋放操作,這里就會報錯

??????????? _free_dbg( pUserData, pHead->nBlockUse );

??????? __FINALLY
??????????? _munlock(_HEAP_LOCK); /* release other threads */
??????? __END_TRY_FINALLY

??????? return;
}
如果在里面設(shè)置斷點,無論是直接調(diào)用::operator delete還是類似delete p調(diào)用對象的operator delete,如果沒有人為override,都會進入這個函數(shù),進行釋放內(nèi)存的操作。因此一個C++的類其實可以看做是有一個類似java的Object在內(nèi)部進行操控:

class object {
public :
??????? object() { }
??????? ~object() { }
??????? void operator delete(void *ptr) {
??????????????? ::operator delete(ptr);
??????? }
};

delete原語看起來會是如下的樣子:
p->~object();
object::operator delete(p);

因為代碼段的內(nèi)存是不會被釋放的,因此無論對象p的內(nèi)存有沒有釋放,這兩個語句都會執(zhí)行,不會因為p沒有指向任何存在的對象而報錯,只是在最后執(zhí)行到::operator delete的時候,才會在執(zhí)行_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse))的時候報錯。

Example 4: 代碼段不會被釋放
class x {
public :
??? x(){printf("x()/n"); }
??? ~x() {
??????? printf("~x()/n");
??????? operator delete(this);
//以下并不會報錯
??????? int n=~get(34);//返回-6(~5)
??????? x(); //會連帶調(diào)用x()->~x()->operator delete
??? }
??? void operator delete(void *p) { // 這其實是一個靜態(tài)函數(shù) ,成員函數(shù)調(diào)用不能放在里面
??????? ::operator delete(p);
??????? printf("x::delete()/n");
??? }
??? int get(int ) { //注意這個申明是合法的
??????? printf("x::get()/n");
??????? return 5;
??? }
};

int main()
{
??? x* p=new x;
??? x::x(); //合法的,會連帶調(diào)用x()->~x()->operator delete,但會因為具體對象不存在而報錯
??? //p->x(); //調(diào)用非法,編譯不通過
??? delete p;
??? int num = p->get(1); //不會報錯,返回5
}

Example 5: 釋放內(nèi)存只釋放數(shù)據(jù)段
class x {
public :
??? int n;
??? x() {
??????? printf("x()/n");
??????? n=5;
??? }
??? ~x() {
??????? printf("~x()/n");
??? }
??? void operator delete(void *p) { // 這其實是一個靜態(tài)函數(shù) ,成員函數(shù)調(diào)用不能放在里面
??????? ::operator delete(p);
??????? printf("x::delete()/n");
??? }
??? int get(int ) {
??????? printf("x::get()/n");
??????? return n;
??? }
??? void test() {
??????? delete this;
//以下并不會報錯
??????? int n=this->get(34); //會得到一個非法值,不是5
??? }
};

int main()
{
??? x* p=new x;
??? p->test();
??? delete p;
??? int num = p->get(1); //會得到一個非法值,不是5
}

對象析構(gòu)談—— delete this 的使用及注意事項


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产在线不卡视频 | 日本在线观看a | 亚洲精品色一区二区三区 | 国产一级毛片国语版 | 亚洲一区日韩二区欧美三区 | 亚洲国产资源 | 欧美高清精品 | 久热中文字幕在线观看 | 日韩在线中文字幕 | 波多野给衣一区二区三区 | 国产精品视频第一区二区 | 国产亚洲精品麻豆一区二区 | 天天插天天干天天操 | 亚洲综合精品一区二区三区中文 | 国产成人精品免费视频大全办公室 | 国产a毛片高清视 | 亚洲成人免费视频 | 精品国产一区二区三区不卡 | 亚洲啪啪看看 | 久久香蕉国产 | 亚洲三级欧美 | 久久中文字幕亚洲精品最新 | 一级片视频免费看 | 日本免费人成黄页网观看视频 | 国产精品成人第一区 | 午夜成人在线视频 | 成人伊人青草久久综合网 | 91探花在线视频 | 亚洲欧美另类视频 | 精品国产一区二区三区www | 激情亚州 | 久久久99精品久久久 | 国产高清在线精品一区二区三区 | 一 级 黄 中国色 片 | 久久欧美久久欧美精品 | 一级毛片高清大全免费观看 | 香蕉久久国产 | 亚洲不卡一区二区三区在线 | 欧美日韩综合在线视频免费看 | 国产精品久久成人影院 | 69精品久久久久 |