1 つの方法は、関数の戻り値を使用しないことです。2番目のケースのように、出力パラメーターのみを使用してください。とにかく、これは公開された COM インターフェイスではすでにルールになっています。
これは「公式」リファレンスですが、典型的なように、最初のケースについても言及していません: http://support.microsoft.com/kb/104138
しかし、コンポーネント内で戻り値を禁止すると、見苦しいコードになります。構成可能性があると、はるかに優れています。つまり、関数を便利にまとめて、ある関数の戻り値を引数として直接別の関数に渡します。
スマート ポインターを使用すると、それが可能になります。これらはパブリック COM インターフェイスでは禁止されていますが、HRESULT 以外の戻り値も禁止されています。その結果、あなたの問題はなくなります。戻り値を使用してインターフェイス ポインターを返す場合は、スマート ポインターを介して行います。また、スマート ポインターにもメンバーを格納します。
ただし、何らかの理由でスマート ポインターを使用したくない場合 (ちなみに、あなたは気が狂っています!)、あなたの推論は正しいと言えます。あなたの関数は「プロパティゲッター」として機能していますが、最初の例ではそうすべきではありませんAddRef。
したがって、あなたのルールは正しいです (ただし、実装にはバグがありますが、発見していない可能性があるため、すぐにわかります)。
この関数はオブジェクトを必要とします:
void Foo(IUnknown *obj);
objメンバー変数に格納する場合を除き、 の refcountに影響を与える必要はまったくありません。それが戻る前に呼び出すことは、確かにFooの責任であってはなりません! 作成される混乱を想像してください。Releaseobj
この関数はオブジェクトを返します。
IUnknown *Bar();
そして、ある関数の出力を別の関数に直接渡すことで、関数を構成することがよくあります。
Foo(Bar());
Bar返されたものの参照カウントを増やしていた場合、これは機能しません。誰が行くのRelease?を呼び出しBarませんAddRef。これは、保存および管理するものを返すことを意味します。つまり、実質的にプロパティ ゲッターです。
また、呼び出し元がスマート ポインターを使用している場合は、次のようになりpます。
p = Bar();
AddRefオブジェクトが割り当てられると、正常なスマート ポインターが移動します。もしもうまくやっBarていたらAddRef、また1カウント漏らしてしまいました。これは実際には、同じ構成可能性の問題の特殊なケースにすぎません。
出力パラメーター (ポインターからポインター) は、構成可能性の問題の影響を同じように受けないため、異なります。
繰り返しますが、スマート ポインターは、2 番目の例を使用して、最も一般的なケースを提供します。
myClass.getObj(&p);
スマート ポインターは、ここでは参照カウントgetObjを実行しないため、実行する必要があります。
今、私たちはバグに来ます。スマート ポインターpが何かに渡されたときに既に何かを指しているとしgetObjます。
修正版は次のとおりです。
void getObj(IUnknown **outObj) 
{
    if (*outObj != 0)
        (*outObj)->Release();
    *outObj = m_obj;
    (*outObj)->AddRef();  // might want to check for 0 here also
}
operator&実際には、人々はその間違いを頻繁に犯すので、スマート ポインターが既にオブジェクトを持っているときに呼び出された場合にアサートする方が簡単だと思います。