2017-04-03 9 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メモリを取得するために、その後がオブジェクト
  • deleteを作成するために提供コンストラクタを呼び出し、その後、オブジェクトのデストラクタを呼び出しますoperator deleteを呼び出してメモリを「返す」。


EDIT:ボーPerssonのは良いアイデアを、指摘していないとして、あなたは、例外の保証に

+3

*オブジェクトが正常に*置換された場合。コンストラクタがスローすると、まだトーストしています。 –

+0

メモリが解放される前にオブジェクトの破壊が発生する必要がある場合は、C++に "このポインタは破壊されたがまだ削除されていないオブジェクトによって使用された割り当てられたストレージを識別します。デストラクタを呼び出す "? – supercat

+0

@supercat、はい...しかし、もっと多くの作業が必要になります。ポインタ上で明示的に 'operator delete(obj)'を呼び出すことはできますが、[*クラス固有の*演算子delete'](http://en.cppreference.com/w/cpp/memory/new/operator_delete#クラス固有のオーバーロード)。 'delete' *式が' operator 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; 
} 

、私は非常に驚かれることでしょう問題。それは*の行で同じオブジェクトに対して2つの*デストラクタを呼び出しますので

struct Bar {std::string s;}; 

void testBar() 
{ 
    Bar* bar = new Bar{"test"}; 
    bar->~Bar(); 
    delete bar; 
} 
関連する問題