9

これは、この質問のフォローアップです。私がこのコードを持っているとしましょう:

class Class {
    public virtual method()
    {
        this->~Class();
        new( this ) Class();
    }
};

Class* object = new Class();
object->method();
delete object;

これは、この回答が示唆するものの簡略版です。

これで、オブジェクトの存続期間内からデストラクタが呼び出されると、呼び出し元のコードmethod()のポインタ変数が無効になります。object次に、新しいオブジェクトが同じ場所に作成されます。

これにより、呼び出し中のオブジェクトへのポインタが再び有効になりますか?

4

6 に答える 6

8

これは3.8:7で明示的に承認されています。

3.8オブジェクトの存続期間[basic.life]

7-オブジェクトの存続期間が終了した後[...]、元のオブジェクトが占めていた保存場所に新しいオブジェクトが作成された場合、元のオブジェクトを指すポインタ[...]を使用して次の場合は、新しいオブジェクトを操作します:(この場合に満たされるさまざまな要件)

与えられた例は次のとおりです。

struct C {
  int i;
  void f();
  const C& operator=( const C& );
};
const C& C::operator=( const C& other) {
  if ( this != &other ) {
    this->~C(); // lifetime of *this ends
    new (this) C(other); // new object of type C created
    f(); // well-defined
  }
  return *this;
}
于 2012-09-20T13:33:43.380 に答える
4

objectポインタはいつでも無効になることはありません(デストラクタがを呼び出さないと仮定します)delete this。オブジェクトの割り当てが解除されることはなく、デストラクタと呼ばれるだけです。つまり、内部状態がクリーンアップされます(実装に関しては、標準では、オブジェクトはデストラクタの呼び出し後に破棄されると厳密に定義されていることに注意してください)。まったく同じアドレスで新しいオブジェクトをインスタンス化するためにplacementnewを使用したので、技術的には問題ありません。

この正確なシナリオは、C++標準のセクション3.8.7でカバーされています。

オブジェクトの存続期間が終了した後、オブジェクトが占有していたストレージが再利用または解放される前に、元のオブジェクトが占有していたストレージの場所に新しいオブジェクトが作成された場合、元のオブジェクトを指すポインター、元のオブジェクトを参照するか、元のオブジェクトの名前が自動的に新しいオブジェクトを参照し、新しいオブジェクトの有効期間が開始されると、新しいオブジェクトを操作するために使用できます[...]

とは言うものの、これは学習コードとしてのみ興味深いものであり、本番コードとしては恐ろしいものです:)

于 2012-09-20T12:57:26.387 に答える
4

厳密には、これで問題ありません。ただし、細心の注意を払わない、UBの恐ろしい部分になります。Class()たとえば、このメソッドを呼び出す派生クラスは、正しい型を再構築しません。または、例外をスローした場合はどうなりますか。さらに、これは実際には何も達成しません。

それは厳密にはUBではありませんが、がらくたと失敗の巨大な山であり、一目で燃やされるべきです。

于 2012-09-20T12:53:47.923 に答える
0

ポインタはそのアドレスしか知りません。新しいオブジェクトのアドレスがポインタが指しているアドレスであることを確認できるとすぐに、答えは「はい」になります。

アドレスが変更されないと思われる場合もありますが、Cを使用する場合など、アドレスが変更される場合もありrealloc()ます。しかし、それは別の話です。

于 2012-09-20T12:55:00.967 に答える
0

デストラクタを明示的に呼び出すことを再検討することをお勧めします。実行したいコードがデストラクタにある場合は、そのコードを新しいメソッドに移動し、デストラクタからそのメソッドを呼び出して、現在の機能を保持します。デストラクタは、実際にはスコープ外のオブジェクトに使用することを目的としています。

于 2012-09-20T13:30:50.397 に答える
-2

破棄されたオブジェクトの場所に新しいオブジェクトを作成しても、ポインタは再び有効になりません。それらは有効な新しいオブジェクトを指している可能性がありますが、最初に参照していたオブジェクトを指しているわけではありません。

元のオブジェクトを破棄する前に、すべての参照が削除されたか、何らかの理由で無効としてマークされていることを確認する必要があります。

これは、デバッグが特に難しい状況になります。

于 2012-09-20T12:58:57.560 に答える