参照カウントの実装
参照カウントでは、クラスの実装者と、そのクラスのオブジェクトを使用するクライアントの両方の部分で作業する必要があります。 クラスを実装する場合は、IUnknown インターフェイスの一部として、AddRef メソッドと Release メソッドを実装する必要があります。 これら 2 つのメソッドには、次の簡単な実装があります。
- AddRef は、オブジェクトの内部参照カウントをインクリメントします。
- Release は、最初にオブジェクトの内部参照カウントをデクリメントしてから、参照カウントが 0 に減少したかどうかを確認します。 存在する場合は、誰もオブジェクトを使用していないので、Release 関数はオブジェクトの割り当てを解除します。
ほとんどのオブジェクトの一般的な実装方法は、(QueryInterfaceと共に) これらのメソッドの実装を 1 つだけ持つことです。これは、すべてのインターフェイス間で共有されるため、オブジェクト全体に適用される参照カウントです。 ただし、クライアントの観点からは、参照カウントは厳密かつ明確にインターフェイス ごとのポインターの概念であるため、現在存在しているインターフェイス ポインターに基づいて機能の一部を動的に構築、破棄、読み込み、またはアンロードすることによって、この機能を利用するオブジェクトが実装される可能性があります。 これらは、ティアオフ インターフェイスと俗に呼ばれています。
新しいインターフェイス ポインターを返す、QueryInterfaceなどのメソッド (または API 関数) をクライアントが呼び出すたびに、呼び出されるメソッドは、返されたポインターを介して参照カウントをインクリメントします。 たとえば、クライアントが最初にオブジェクトを作成すると、クライアントの観点から参照カウントが 1 であるオブジェクトへのインターフェイス ポインターを受け取ります。 その後、クライアントがインターフェイス ポインター AddRef を呼び出すと、参照カウントは 2 になります。 クライアントは、Release をインターフェイス ポインターで 2 回呼び出して、オブジェクトへのすべての参照を削除する必要があります。
参照カウントが厳密にインターフェイスごとのポインターである方法の例は、クライアントが新しいインターフェイスまたは同じインターフェイスの最初のポインター QueryInterface を呼び出すときに発生します。 いずれの場合も、クライアントはポインターごとに 1 回、Release を呼び出す必要があります。 COM では、同じインターフェイスを複数回要求されたときにオブジェクトが同じポインターを返す必要はありません。 (これに対する唯一の例外は、オブジェクトを COM に識別する IUnknownをするクエリです)。これにより、オブジェクトの実装でリソースを効率的に管理できます。
スレッド セーフは、AddRef と リリースを実装する際の重要な問題でもあります。 詳細については、「プロセス、スレッド、およびアパートメント」を参照してください。
関連トピック