如果我是用new分配對象的,可以顯式調用析構函數嗎?
可能不行。
除非你使用定位放置 new,否則應該 delete 對象而不是顯式調用析構函數。例如,假設通過一個典型的 new 表達式分配一個對象:
那麼,當你delete它時,析構函數 Fred::~Fred() 會被調用:
由於顯式調用析構函數不會釋放 Fred 對象本身分配的內存,因此不要這樣做。記住:delete p 做了兩件事情:調用析構函數,回收內存。
什麼是“定位放置new(placement new)”,爲什麼要用它 ?
定位放置new(placement new)有很多作用。最簡單的用處就是將對象放置在內存中的特殊位置。這是依靠 new表達式部分的指針參數的位置來完成的:
#include "Fred.h" // class Fred 的聲明
void someCode()
{
char memory[sizeof(Fred)]; // Line #1
void* place = memory; // Line #2
Fred* f = new(place) Fred(); // Line #3 (詳見以下的“危險”)
// The pointers f and place will be equal
// ...
}
Line #1 在內存中創建了一個sizeof(Fred)字節大小的數組,足夠放下 Fred 對象。Line #2 創建了一個指向這塊內存的首字節的place指針(有經驗的 C 程序員會注意到這一步是多餘的,這兒只是爲了使代碼更明顯)。Line #3 本質上只是調用了構造函數 Fred::Fred()。Fred構造函數中的this指針將等於place。因此返回的 f 將等於place。
建議:萬不得已時才使用“placement new”語法。只有當你真的在意對象在內存中的特定位置時才使用它。例如,你的硬件有一個內存映象的 I/O計時器設備,並且你想放置一個Clock對象在那個內存位置。
危險:你要獨自承擔這樣的責任,傳遞給“placement new”操作符的指針所指向的內存區域必須足夠大,並且可能需要爲所創建的對象進行邊界調整。編譯器和運行時系統都不會進行任何的嘗試來檢查你做的是否正確。如果 Fred 類需要將邊界調整爲4字節,而你提供的位置沒有進行邊界調整的話,你就會親手製造一個嚴重的災難(如果你不明白“邊界調整”的意思,那麼就不要使用placement new語法)。
你還有析構放置的對象的責任。這通過顯式調用析構函數來完成:
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
// ...
f->~Fred(); // 顯式調用定位放置的對象的析構函數
}
這是顯式調用析構函數的唯一時機。