2010-09-29 75 views
16

在閱讀this question的答案時,我注意到答案(例如this)意味着即使delete語句在空指針上執行時也可以調用operator delete爲什麼當我在空指針上調用「delete」時調用「operator delete」?

所以我寫了一個小片段:

class Test { 
public: 
    void* operator new(size_t) { /*doesn't matter*/ return 0; } 
    void operator delete(void* ptr) { 
     ptr; //to suppress warning and have a line to put breakpoint on 
    } 
}; 

int main() 
{ 
    Test* ptr = 0; 
    delete ptr; 
} 

和 - 令人驚訝的我 - Test::operator delete()被調用,ptr拿着一個空指針。

據我所知operator new分配內存和operator delete返回分配器的內存。如果我在空指針上調用delete語句,則意味着指針後面沒有對象,並且沒有內存返回到分配器。

delete語句包括調用析構函數。當我傳遞一個空指針時,析構函數肯定不會被調用 - C++負責處理這個問題。那麼爲什麼在這種情況下調用operator delete

+0

問一下爲什麼當你分配零長度數組時,調用operator new:'new Test [0];'...;) – ybungalobill 2010-09-29 13:37:44

+1

@ybungalobill:這很簡單 - 標準要求返回的指針是有效的且不同的。 – sharptooth 2010-09-29 14:08:10

+0

請注意,如果您使析構函數爲虛擬,則不會調用重載'operator delete'。實現通常直接從析構函數調用該函數,並在不檢查null的情況下調用析構函數(從而節省一些指令)。只有當呼叫需要虛擬調度時纔是預先執行的檢查。 – avakar 2010-09-29 14:11:10

回答

18

在即將到來的C++ 0x標準的語言(第5.3.5節[expr.delete])被調用如下:

如果 的操作數的值不是空指針值 ,則刪除表達式 將調用釋放函數 (3.7.4.2)。否則,未指定 函數是否會調用釋放 函數。 [注意: 解除分配函數稱爲 ,不管對象的析構函數 還是 數組的某個元素都引發異常。 - 注完]

所以它是不確定的行爲,一些編譯器可以調用operator delete當NULL指針被刪除,其他人可能不會。

編輯:術語釋放函數使用的標準似乎是造成一些混淆。它帶有一個參考。從3.7.4.2 [basic.stc.dynamic.deallocation]一些關鍵的語言可能有助於澄清:

如果一個類T有一個名爲operator delete 恰好與一個參數一個成員釋放功能,該功能是通常(非配置)釋放的功能。

該標準也很清楚的是用戶定義operator delete需要接受一個參數,該參數是一個空指針值:

的 第一個參數的供應給釋放函數的值可以是一個空指針值;如果是這樣,並且如果釋放 函數是標準庫中提供的函數,則該調用不起作用。

但由於未指定的行爲5.3.5,當指針爲空時,不應該依賴於您調用的operator delete

+0

嗯,這個片段談論的是釋放功能,而不是操作員。 – 2010-09-29 13:36:29

+0

C++ 03在這個問題上似乎含糊不清。它說「如果刪除操作數的值是空指針操作 沒有效果」,那麼,「如果刪除表達式調用 執行釋放函數...」,那麼「刪除表達式將調用一個釋放函數「。所以要麼不能調用重載操作符,要麼沒有指定,或者必須調用它。其中之一;-) – 2010-09-29 13:40:40

+0

@Hans:釋放函數是實現'operator delete'的函數。這個術語來自於操作符出現在表達式中的事實,而實現它們的函數是*函數。換句話說,你需要以某種方式分離你的術語。 – ybungalobill 2010-09-29 13:41:26

10

運算符刪除就像任何其他運算符一樣,爲什麼它不被調用?在調用之前,它無法檢查其參數

這就好比問爲什麼operator+當你添加0

+10

'delete'語句不只是調用'operator delete',它首先調用析構函數,並且在調用析構函數之前(因此在調用'operator delete'之前)必須執行一個空的檢查。 'operator delete'不像其他的操作符重載。 – 2010-09-29 13:12:55

+0

好的,但編譯器無法確定在給定空指針時用戶定義的操作符delete是否爲空操作。例如,它可以記錄表明你試圖刪除空指針的東西。 – 2010-09-29 13:16:32

+2

同意Ben Voigt:當你鍵入'delete p;'時,編譯器首先調用對象的析構函數,然後調用釋放函數'operator delete'。系統必須能夠診斷指針爲0,以避免調用析構函數(它不會調用它),所以在技術上它也可以避免調用deallocator。 – 2010-09-29 13:19:42

相關問題