關於placement new操作

如果我是用new分配對象的,可以顯式調用析構函數嗎?

可能不行。

除非你使用定位放置 new,否則應該 delete 對象而不是顯式調用析構函數。例如,假設通過一個典型的 new 表達式分配一個對象:

 

 Fred* p = new Fred();

那麼,當你delete它時,析構函數 Fred::~Fred() 會被調用:

 delete p;  // 自動調用 p->~Fred()

由於顯式調用析構函數不會釋放 Fred 對象本身分配的內存,因此不要這樣做。記住:delete p 做了兩件事情:調用析構函數,回收內存。 



什麼是“定位放置new(placement new)”,爲什麼要用它 ?

定位放置new(placement new)有很多作用。最簡單的用處就是將對象放置在內存中的特殊位置。這是依靠 new表達式部分的指針參數的位置來完成的:

 

 #include <new>        // 必須 #include 這個,才能使用 "placement 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語法)。

你還有析構放置的對象的責任。這通過顯式調用析構函數來完成:

 void someCode()
 {
   char memory[sizeof(Fred)];
   void* p = memory;
   Fred* f = new(p) Fred();
   
// ...
   f->~Fred();   
// 顯式調用定位放置的對象的析構函數
 }

這是顯式調用析構函數的唯一時機。 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章