web-dev-qa-db-ja.com

「これを削除」しても大丈夫ですか?

私の最初の基本的なテストでは、そうすることは完全に安全です。しかし、後でthiss deleteという関数でthisを操作しようとすると、ランタイムエラーになる可能性があることに気づきました。これは本当ですか、そして通常はdelete this?それとも安全な特定のケースだけがありますか?

33
Cristián Romo

_delete this_は合法であり、期待どおりの動作をします。クラスのデストラクタを呼び出し、基になるメモリを解放します。 _delete this_が戻った後、thisポインタ値はnot変更されるため、not逆参照する必要があるダングリングポインタになります。これには、クラスのメンバー変数を使用した暗黙的な逆参照が含まれます。

通常、参照カウントクラスでは、ref-countが0にデクリメントされると、DecrementRefCount()/Release() /任意のメンバー関数が_delete this_を呼び出すことがわかります。

_delete this_は通常、多くの理由で非常に悪い形式と見なされます。 _delete this_の後に誤ってメンバー変数にアクセスするのは簡単です。呼び出し元のコードは、オブジェクトが自己破壊したことに気付かない場合があります。

また、_delete this_は「コードの臭い」であり、コードにはオブジェクトの所有権(誰が割り当て、誰が削除するか)について対称的な戦略がない可能性があります。 オブジェクトはnewで自分自身を割り当てることができなかったので、_delete this_を呼び出すと、クラスAがオブジェクトを割り当てますが、クラスBは後でオブジェクトを解放します[self]。

46
Chris Peterson

それが本質的にメソッドの最後の操作である限り、「this」を削除しても安全です。実際、いくつかのプロフェッショナルレベルのAPIがそうしています(例については、ATLのCComObject実装を参照してください)。

唯一の危険は、「これを削除」を呼び出した後に他のメンバーデータにアクセスしようとすることです。これは確かに安全ではありません。

16
JaredPar

他の人がすでに述べたように、これを削除することは完全に合法です。まだ言及されていないもう1つの理由で、リスクがあります。オブジェクトがヒープに割り当てられていると想定しています。参照カウントの実装の場合、一般的に問題はありませんが、これを保証するのは難しい場合があります。

13

しかし、デストラクタではそれをしないでください!

13
al pacino

他の人が述べているように、これを削除することは有効なイディオムですが、安全のために、オブジェクトがスタック上でインスタンス化されないようにする必要があります。

これを行う1つの方法は、コンストラクタとデストラクタの両方をプライベートにし、ヒープ上にオブジェクトを作成してそのオブジェクトへのポインタを返すクラスファクトリ関数を介してオブジェクトの作成を強制することです。クラスファクトリは、静的メンバー関数またはフレンド関数にすることができます。クリーンアップは、「これを削除」するオブジェクトのDelete()メソッドを介して実行できます。 COMオブジェクトは基本的にこのように機能しますが、参照カウントがゼロに減少したときに「これを削除」が発生して参照カウントされる点が異なります。

6
Bruce Ikin

はい。それは完全に大丈夫なはずです。 「これ」は単なるポインタです。どんなポインタでも削除できます。オブジェクトを削除する方法に関する情報は、ヒープレコードに含まれています。これは、IUnknown :: Release()が通常COMオブジェクトに実装される方法です。

3
Steve Rowe

これを削除すると、削除するオブジェクトのサブクラスがある場合に問題が発生する可能性があります。構築は上から始まり、削除は下から始まることを忘れないでください。したがって、これを削除すると階層の中央にあるため、基本的にこの特定のクラスの下にあるすべてのオブジェクトが失われます。

これを削除すると、COMクラスなどの参照カウントオブジェクトを実装するときに非常に便利です。

3
rptony

法務はい
安全いいえ

2
Martin York

読む 同様の議論のために。あなたの理解は、それが機能し、必要であり、後でこれにアクセスできないので危険である可能性があるという点で正しいです。

2
hacken