2011-11-15 62 views
4

可能重複:
Deleting a pointer to const (T const*)爲什麼在「操作符刪除」中將「const T *」簡單地轉換爲「void *」?

void operator delete (void*); 
... 
const char *pn = new char, *pm = (char*)malloc(1); 
delete pn; // allowed !! 
free(pm); // error 

Demo

這是可以理解的free()是一個函數,所以一個const void*不能轉換爲void*。但爲什麼在operator delete(默認或超載)的情況下允許?

它在功能上不是一個錯誤的構造嗎?

+0

無論如何,刪除一個'void *'是UB,所以誰在乎? – tenfour

+1

它的答案在這裏:http://stackoverflow.com/questions/755196/deleting-a-pointer-to-const-t-const –

+0

@tenfour,以及'const T *'應先轉換爲'T *',然後它被轉換爲void *'。所以它不應該是UB。否則,所有'刪除'都是UB。 – iammilind

回答

2

儘管我完全同意@詹姆斯·坎澤的回答,也許有人想看看標準實際上說了些什麼。根據標準(§12.1/ 4):

const和volatile語義(7.1.5.1)不適用於 構造下的對象。這種語義只有在最衍生對象(1.8) 的構造函數結束後纔會生效。

和(§12.4/ 2):

常量和 揮發性語義(7.1.5.1)不被應用下破壞的對象上。一旦最大派生對象(1.8)的析構函數啓動,這樣的語義就會停止生效 。

公平地說,這比重新狀態多一點什麼@詹姆斯說,有點更具體:對象是唯一真正考慮從時間對象的構造函數完成(或所有的構建函數,當繼承涉及)到第一個dtor開始的地步。在這些邊界之外,const和volatile會被強制執行。

+0

有一個微妙的區別。 James說:「破壞之後,你留下了一個'void *'。」標準說,「這種語義在大多數派生對象(1.8)的析構函數開始後不再生效。」所以,從詹姆斯所說的話中,有人可以推斷出'const'語義在析構函數執行期間仍然有效,並且是錯誤的。不過,這確實是挑剔的。 –

4

不是。 delete表達式首先調用析構函數。 經過 銷燬,您剩下一個void*。 (典型的實現, 其實已經析構函數調用operator delete()功能,因爲 這operator delete()調用依賴於最派生類。)

至於爲什麼你T const*成爲析構T*:這是任何 不同於:

{ 
    T const anObject; 
    // ... 
} // destructor of anObject called here. With T*, not T const* 

?人們可以爭辯不同的規則,但最終,破壞者是特殊的,並遵守特殊規則。

+0

換句話說,破壞會拋棄'const'。 –

+0

@MikeDeSimone:我以另一種方式看待它。 'const'只適用於有生命的物體。構造函數和析構函數在這個生命週期之外執行,所以它不適用於它們。 –

+0

@MikeDeSimone或忽略它。析構函數和構造函數總是用類型來玩遊戲,那麼更多的異常是什麼? –

相關問題