2017-04-03 22 views
3
auto obj = new Object; 
obj->~Object(); 
delete obj; 

我知道這是不尋常的,但它是定義的行爲?它能引起任何令人驚訝的問題嗎?刪除之前手動調用析構函數

+0

萬一它不完全是顯而易見WhiZTiM的答案,爲什麼它的不確定的原因是因爲它會調用*爲連續同一物體的兩個*析構函數。 – HolyBlackCat

回答

8

你只能做如果更換由obj有一個新的對象指向按照被破壞的對象:

auto obj = new Object; 
obj->~Object(); 

new (obj) Object(); 
delete obj; 

否則,調用未定義的行爲。


您應該明白:

  • new電話operator new獲得內存,然後調用提供construtor創建對象
  • delete調用對象的析構函數,然後調用operator delete來「返回」內存。


編輯:博佩爾鬆指出的那樣,它不是,如果你不能提供異常的好主意保證

+3

如果*成功*替換該對象。如果構造函數拋出,你仍然敬酒。 –

+0

如果有必要在釋放內存之前發生對象的破壞,是否有任何告訴C++的方式「該指針標識已被破壞但尚未刪除的對象所使用的已分配存儲空間;請釋放存儲空間調用析構函數「? – supercat

+0

@超級貓,是的......但它需要更多的工作。雖然你可以在指針上顯式調用operator delete(obj),但在有[* class-specific *'operator delete']的情況下會失敗(http://en.cppreference.com/w/cpp /存儲器/新/ operator_delete#類specific_overloads)。當'delete' *表達式*調用'操作符delete(...)'時,標準要求它首先檢查*特定類*的重載。但是當你在你的代碼中明確地調用'operator delete'時,這[不會發生](http://coliru.stacked-crooked.com/a/7e4c76a444a8d8cf)。 – WhiZTiM

1

它是未定義行爲造成的對象析構函數被調用兩次。你沒有遵循規則,編譯器可以隨你的代碼做任何事情。只需不要那樣做

0

如果我們嚴格遵守標準語言,您的代碼會導致未定義的行爲,並會導致問題。

不過,我會很驚訝,如果任何平臺將遇到任何問題,以下內容:

struct Foo {}; 

void testFoo() 
{ 
    Foo* foo = new Foo(); 
    foo->~Foo(); 
    foo->~Foo(); 
    foo->~Foo(); 
    foo->~Foo(); 
    foo->~Foo(); 
    foo->~Foo(); 
    foo->~Foo(); 
    delete foo; 
} 

在另一方面,我會很驚訝,如果任何平臺都可以執行以下,而不會在問題。

struct Bar {std::string s;}; 

void testBar() 
{ 
    Bar* bar = new Bar{"test"}; 
    bar->~Bar(); 
    delete bar; 
}