1

私は単純な Direct2D アプリケーションを作成する方法のSafeReleaseを研究しており、作成者は次のようにクラス テンプレートとメソッドを定義しています。

    template<class Interface>
inline void SafeRelease(
    Interface **ppInterfaceToRelease
    )
{
    if (*ppInterfaceToRelease != NULL)
    {
        (*ppInterfaceToRelease)->Release();

        (*ppInterfaceToRelease) = NULL;
    }
}

上記のコードは、ヘッダー ファイルからのものです。ただし、クラスのデストラクタは次の呼び出しを行います。

DemoApp::~DemoApp()
{
    SafeRelease(&m_pDirect2dFactory);
    SafeRelease(&m_pRenderTarget);
    SafeRelease(&m_pLightSlateGrayBrush);
    SafeRelease(&m_pCornflowerBlueBrush);

}

私は c++ の学習を始めたばかりで、どうしてこれらの呼び出しが合法なのか疑問に思っています。明らかに、プロシージャ パラメーターとしてのポインターの理解に欠陥があるため、修正してください。ポインタ型を受け入れるプロシージャは、どのようにしてアドレスを受け入れることができますか? また、F12 を押しても Visual Studio はReleaseメソッドの宣言を見つけることができませんが、COM のリリース メソッドと関係があると思われます。デバッグ時に「ステップイン」します。コードは問題なく動作しますが、その理由が気になります。完全なソース コードはここにあります。

4

1 に答える 1

3

物事を単純化するのに役立ち、基本的にメモリを 1 つの巨大な配列と考えてください。そこにはアドレス (配列へのインデックスと考えることができます) があり、実際にはコンテンツ自体 (何でもかまいません) があります。 )。

したがって、Interface ** は、Interface オブジェクトを含む別のメモリ アドレスを含むメモリを指すアドレスと考えることができます。

次のことを想像してください

 Name               Type               Memory Address           Contents

 interfacePtrPtr    Interface**        0x1                      The address 0x2
 interfacePtr       Interface*         0x2                      The address 0x3
 interface          Interface          0x3 - 0xFF?              An interface object

この架空の例では、 interface から始めて&interfaceを使用してinterfacePtrを取得し、& interfacePtr を使用して interfacePtrPtrを取得したとします。

さかのぼって *interfacePtrPtr を使用して interfacePtr を取得し、次に *interfacePtr を使用して最終的にインターフェース自体に戻ることもできます。

あなたの例では、いつ

  SafeRelease(&m_pDirect2dFactory);

が呼び出されると、関数にはインターフェイス ポインターのアドレスが与えられます (必要に応じて、インターフェイス ポインター ポインター)。

  (*ppInterfaceToRelease)->Release();

次に、このポインターを * で逆参照し、ポインター ポインターを通常のポインターに変換してから、-> ショートハンドを使用してポインターを Interface オブジェクト自体に逆参照し、その release メソッドを呼び出します。

これが理にかなっていることを願っています。

于 2013-06-15T13:18:14.297 に答える