安`削除`?[重複]
-
23-08-2019 - |
質問
この質問に答えはこちら
- は削除することです。 10答
私の初期の基本試験では、完全に安全に行えるようになった。しかし、印象に残っていることを操作する this
その後、機能 delete
s this
するランタイムエラーが発生します。はたしてそうなので、通常の安全な delete this
?やが一定の場合に記載ので安全ですか?
解決
delete this
は合法で、あなたが期待する何を:それはあなたのクラスのデストラクタを呼び出して、基本的なメモリを解放します。 delete this
戻った後、あなたのthis
ポインタ値がのないの変更を行い、それが今、のないの逆参照しなければならないダングリングポインタですので。これは、クラスのメンバ変数を使用して、暗黙の参照解除を含んでます。
これは通常REFカウントが0までデクリメントされ、参照カウントクラスに見出される、DecrementRefCount()
/ Release()
/どのメンバ関数はdelete this
を呼び出します。
delete this
は、一般的に多くの理由のために非常に悪い形と考えられています。偶然delete this
後にメンバ変数にアクセスすることは容易です。あなたの目的を達成しない場合があります発信者コードが自己消滅持っています。
また、delete this
はあなたのコードは、オブジェクトの所有権(割り当ておよび削除)について対称な戦略を持っていないかもしれないことを「コードのにおい」です。 <ストライキ>オブジェクトはそうnew
を呼び出すと、クラスAがオブジェクトを割り当てているが、クラスBは、後で[自己]を、それを解放していることを意味し、delete this
で自身を割り当てられていることができなかった。ストライク>
他のヒント
これは、限り、それは本質的方法における最後の操作だとして「この」を削除しても安全です。実際には、いくつかのプロレベルのAPIは、(例えばATLのCComObjectの実装を参照してください)そう。
唯一の危険は、「これを削除し、」呼び出した後、他のメンバーのデータにアクセスしようとしています。これは確かに安全ではありません。
他の人がすでに述べてきたように、これは完全に合法で削除します。あなたがオブジェクトをヒープに割り当てられていることを想定している - それはまだ言及されていない一つの追加の理由で危険です。参照カウントの実装の場合には、一般的に問題とならないが、これは、保証が困難であることができる。
が、デストラクタでそれを行ういけない!
他の人が述べたように、これが有効なイディオムで削除しても、それは安全であるためには、オブジェクトがスタックにインスタンス化されないことを確認する必要があります。
これを行う1つの方法は、コンストラクタとデストラクタの両方をプライベートにして、ヒープ上のオブジェクトを作成し、そのポインタを返すクラスファクトリ関数を介してオブジェクトの作成を強制することです。クラスファクトリは、静的メンバ関数や友人の関数とすることができます。クリーンアップは、「これを削除し、」ないオブジェクトのDelete()メソッドを介して行うことができます。 COMオブジェクトは、基本的に、彼らが参照カウントがゼロにされたときに発生する「これは削除」を参照カウントされているほかにことを除いて、このように動作します。
はい。それは完全に罰金する必要があります。 「これは」単なるポインタです。任意のポインタは、削除のために行います。オブジェクトを削除する方法についての情報は、ヒープレコードに含まれています。これはIUnknownの::リリース()は通常のCOMオブジェクトに実装されている方法です。
あなたが削除されたオブジェクトのサブクラスを持っている場合、これは問題を引き起こす可能性があります削除します。トップダウンからの着工を忘れないでください、削除がボトムアップから始まります。だから、これを削除する場合は、あなたは基本的に、この特定のクラスの下にあるすべてのオブジェクトを失った階層の真ん中にある。
あなたが参照カウントオブジェクト、COMクラスとなっている例を実装する際に、これは非常に便利来る削除します。
似議論のためをお読みください。あなたの理解はそれが仕事をすることで、権利である必要がある、とあなたが、その後これをアクセスすることはできませんので、危険なことができます。
法律はい
金庫はありません。
あなたがクラッシュを引き起こします派生クラスのポインタを使用して、基本クラスから継承し、基本クラスの機能でこれを削除したしている場合。例えばます:
class Base
{
virtual void Release()
{
delete this;
}
}
class Derived : public Base
{
void Foo()
{
...
}
}
main()
{
Base *ptrDerived = new Derived();
ptrDerived->release();
ptrDerived->Foo() //Crash
}