Destructors實質是釋放資源;
類的析構執行順序是先構造(Constructed)的(成員),最后被Destructors,數組成員同樣如此,例如:數組a[0], a[1], ..., a[8], a[9]: 析構執行順序是a[9], a[8], ..., a[1], a[0]:不能有參數,不能有返回值,不能重載;只能在(對象關閉)自動調用,不能顯示調用析構函數(除非placement new),不可以調用兩次。
值得注意的是不能顯式調用析構函數,即使局部變量也不行。此時我們需要這樣處理:
void someCode()
{
{
File f;
...........
}
// f 的析構函數在此處會被自動調用!
}
如果上述的方案還是不可行,我們可以考慮增加一個和析構函數等效的成員方法,例如:我們常見File類,就可增加一個Close()成員方法,但是要記住和析構函數一樣,不能聯系調用兩次,我們可以將一個fileHandle_數據成員設置為 -1,并且在開頭檢查fileHandle_是否已經等于-1;
class File {
public:
void close();
~File();
...
private:
int fileHandle_; // fileHandle_ >= 0 if/only-if it's open
};
File::~File()
{
close();
}
void File::close()
{
if (fileHandle_ >= 0) {
...insert code to call the OS to close the file...
fileHandle_ = -1;
}
}
如果一個對象是new的,那么在delete中也不能顯示調用析構函數,因為delete做了兩件事,調用析構銷毀對象和釋放空間。這里的new可不是operator new,后者只是分配空間,并沒調用構造函數。
placement最明顯的作用就是把對象放到特定的內存位置。
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)]; // Line #1
void* place = memory; // Line #2
Fred* f = new(place) Fred(); // Line #3 (see "DANGER" below)
// The pointers f and place will be equal
...
}
Line #3中的構造函數中的this指針將等于place,f的返回值也是place,注意:placenew指向的指針要有足夠的空間,并且需要為所創建的對象進行邊界調整,編譯器和系統不會對此進行任何檢查,另外placenew的析構應該像如下這樣編寫:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
...
f->~Fred(); // Explicitly call the destructor for the placed object
}
在編寫析構函數時,也不能顯正調用成員的析構函數,類的析構函數會自動調用成員的析構,按照和它們在類中的聲明的順序相反的順序被析構。
在派生類的析構中,不能顯式調用基類的析構。派生類的析構會自動調用基類的析構函數。在多重繼承的情況下,直接基類以出現在繼承列表中的順序的反序被析構。