首先轉載一下牛人的文章,我覺得寫得不錯:http://www.cppblog.com/lovedday/archive/2008/06/03/52060.html
內容如下:
In order to understand "delete this" :
First Step------dive into "delete p"
delete p 執行了哪兩個步驟?
delete p 是一個兩步的過程:調用解構函式,然後釋放記憶體。delete p產生的代碼看上去是這樣的(假設是Fred*類型的):
// 原始碼:delete p;
if (p != NULL)
{
p->~Fred();
operator delete(p);
}
p->~Fred() 語句調用 p 指向的Fred 對象的解構函式。
operator delete(p) 語句調用記憶體釋放原語 void operator delete(void* p)。
Second Step-------"delete this"
成員函數調用delete this合法嗎?
只要你小心,一個對象請求自殺(delete this),是可以的。
以下是我對“小心”的定義:
你必須100%的確定,this對象是用 new分配的(不是用new[],也不是用定位放置 new,也不是一個棧上的局部對象,也不是全域的,也不是另一個對象的成員,而是明白的普通的new)。
你必須100%的確定,該成員函數是this對象最後調用的的成員函數。
你必須100%的確定,剩下的成員函數(delete this之後的)不接觸到 this對象任何一塊(包括調用任何其他成員函數或訪問任何資料成員)。
你必須 100%的確定,在delete this之後不再去訪問this指標。換句話說,你不能去檢查它,將它和其他指標比較,和 NULL比較,列印它,轉換它,對它做任何事。
自然,對於這種情況還要習慣性地告誡:當你的指標是一個指向基類類型的指標,而沒有虛解構函式時(也不可以 delete this)。
注意:因為是在類成員函數裡面delete this的,所以在此語句以後,不能訪問任何的成員變數及虛函數,否則一定非法。
我考慮到了另一種情況:如果父類有個成員函數DeleteMyself,專門做這種自殺行為,而子類沒有這個函數:
#include <iostream>
using namespace std;
class Animal
{
public:
Animal();
~Animal();
virtual void Shout();
void Name();
virtual void DeleteMyself();
private:
bool mbOld;
};
Animal::Animal():mbOld(false)
{
cout<<"Animal Born"<<endl;
}
Animal::~Animal()
{
mbOld = false;
cout<<"Animal time was gone!"<<endl;
}
void Animal::Shout()
{
cout<<"I am animal"<<endl;
}
void Animal::Name()
{
cout<<"My name is animal"<<endl;
}
void Animal::DeleteMyself()
{
delete this;
}
class Dog : public Animal
{
public:
Dog();
virtual ~Dog();
void Shout();
void Name();
};
Dog::Dog()
{
cout<<"Dog born"<<endl;
}
Dog::~Dog()
{
cout<<"Dog time was gone"<<endl;
}
void Dog::Shout()
{
cout<<"I am dog"<<endl;
}
void Dog::Name()
{
cout<<"My name is dog"<<endl;
}
void main()
{
Animal* pMyAnimal = new Dog;
pMyAnimal->Shout();
pMyAnimal->Name();
pMyAnimal->DeleteMyself();
cin.get();
}
那麼結果會是什麼樣子呢?父類的解構函式如果是虛函數會怎樣呢? 子類在記憶體中內否釋放乾淨呢?
首先看一下結果,父類的解構函式非虛,結果是:
Animal Born
Dog born
I am dog
My name is animal
Animal time was gone!
等於說:子類還是沒有釋放。
當父類的解構函式為虛時,結果是:
Animal Born
Dog born
I am dog
My name is animal
Dog time was gone
Animal time was gone!
那麼看來子類的解構函式是調用了,但是子類的記憶體釋放乾淨了嗎?
這裡我不敢肯定子類的記憶體釋放乾淨了,所以保險的做法是,在子類中重寫DeleteMyself。