11

QueryInterface()呼び出しの後に常に呼び出しが続くのはなぜRelease()ですか? たとえば、MSDN のサンプル コードは次のとおりです。

HRESULT hr = S_OK;
CDecoder *pObj = new CDecoder(&hr);

if (SUCCEEDED(hr))
{
    *ppv = NULL;
    hr = pObj->QueryInterface(riid, ppv);
}
pObj->Release();
return hr;

Release()誰かがここでの呼び出しの背後にある意図を説明できますか?

4

3 に答える 3

16

それはかなり一般的ですが、常にこのように直接続くわけではありません。

COM オブジェクトは参照カウントされます。オブジェクトを最初に作成すると、IUnknown. 次に、 との他のインターフェイスを取得しますQueryInterfaceIUnknownあなたは(通常)インターフェースをもう気にしないので、それを解放します。取得した他のインターフェースを解放すると、参照カウントが 0 になるため、オブジェクトを破棄できます。ただし、を解放しないIUnknownと、参照カウントがゼロ以外のままになるため、オブジェクトを破棄できません。

をすぐに解放しない最も明白なケースはIUnknown、複数の他のインターフェイスを取得する必要がある場合です。このような場合、 を取得しIUnknown、次に 2 番目と 3 番目のインターフェイスを取得してから を解放しIUnknownます。少なくとも、オブジェクトを作成した直後に 3 番目 (またはそれ以降) のインターフェイスがわからない可能性があるため、オブジェクトをIUnknown解放する前に、任意の時間アクセスを保持する必要がある場合があります。

于 2011-02-18T23:43:25.250 に答える
8

QueryInterface 呼び出しの後に必ず Release 呼び出しが続くのはなぜですか?

QueryInterfaceはAddRefを呼び出し、ポインターへの参照カウントを増やすためです。ポインターへの参照が 0 の場合、ポインターは解放されます。

注:この質問の回答には、QueryInterface実際に何をするかについて混乱があります。オブジェクトでサポートされているインターフェイスへのポインターを取得し、そのオブジェクトの参照カウントをインクリメントするだけです。実装するインターフェイスごとに新しいオブジェクトを作成しません。

たとえば、2 つのインターフェイスを実装するオブジェクトがある場合、呼び出しは単にそのオブジェクトを各インターフェイスとしてキャストし、参照カウントとして使用される変数をインクリメントします。

注: 参照カウントはさまざまな方法で実装できますが、上記では通常のシナリオについて説明しています。特に @Ben は、以下のティアオフ インターフェイスについて説明しています。これは、返されたインターフェイス ポインターで Release を呼び出すことの重要性を強調しています。

于 2011-02-18T23:39:07.513 に答える
4

この特定のコード スニペットは、ppv値の取得のみに関心があるようです。インターフェイス ポインタが解放されるわけではないことに注意してください。CDecoder クラスは、それを取得する手段のようです。それを作成するための新しいステートメントがあります。それ以外の場合は、COM クラスを作成する標準的な COM の方法ではなく、CoCreateInstance() を使用します。どうやらそのクラスを適切に使用するには、削除演算子を使用する代わりに Release() 呼び出しが必要です。繰り返しますが、まったく標準ではありませんが、不可能ではありません。CDecoder は COM コクラスを実装する C++ クラスであり、このコードは通常の COM プロシージャを経由するのではなく直接使用していると推測できます。

このコードが標準であると想定しないでください。それはまったくありません。

于 2011-02-19T00:43:11.470 に答える