VS2008で次のC++/CLIコードをビルドすると、CA1001のコード分析に関する警告が表示されます。GCが自動的にクラスのメンバーを処分しないのはなぜですか?
ref class A
{
public:
A() { m_hwnd = new HWND; }
~A() { this->!A(); }
protected:
!A() { delete m_hwnd; }
HWND* m_hwnd;
};
ref class B
{
public:
B() { m_a = gcnew A(); }
protected:
A^ m_a;
};
警告:CA1001:Microsoft.Design: 'A': が、それは次のよう IDisposableインター種類のメンバーが作成されます ので、 'B' にIDisposableを実装します。
この警告を解決するには、私は、クラスBにこのコードを追加する必要があります:
~B() { delete m_a; }
しかし、私はなぜ理解していません。クラスAは、デストラクタ(およびファイナライザ)を介してIDisposableを実装します。
確実にAがガベージコレクションされると、Aのファイナライザまたはデストラクタが呼び出され、アンマネージリソースが解放されます。
なぜAメンバーの「削除」を呼び出すためにBがデストラクタを追加する必要がありますか?
Bが明示的に "delete m_a"を呼び出す場合、GCはAのデストラクタを呼び出しますか?
編集:
ref class B
{
public:
B() { }
protected:
A m_a;
};
が、これは常に可能ではない:あなたがこのように、メンバーを宣言する「シンタックスシュガー」メソッドを使用している場合、これは自動的に動作ようです。
なぜ、他の誰もそれにポインタを持っていなければ、A ^のマネージリファレンスポインタを自動的に破棄するのにGCが巧妙ではないのですか?
おかげで、それは私がシンタックスシュガーの方法を使用することができることを本当だ - 私はこれを行う場合、実際に私は(まあ、それはとにかく警告を抑制することができる)すべてのデストラクタを実装する必要はありません。しかし、ほとんどの状況では、構文sugarメソッドを使用することはできません。管理された参照ポインターしか格納できません。管理対象オブジェクトを破棄するために、GCが管理参照ポインタを削除するための明示的な呼び出しを必要とする理由を知りたい。 – demoncodemonkey
"多くのクラスが同じA ^ポインタを保持できるため、デストラクタを呼び出す必要があるかどうかを知る方法がありません" <<どのGCが最後のものかを知ることができなければならず、最後のものが解放されたらデストラクタを呼び出す必要があります。 GCがそれほど驚くべきものではないと思われます。 – demoncodemonkey
あなたの言ったように私のコードをリファクタリングできるかどうかチェックします。 – demoncodemonkey