参照カウントの使用
このドキュメントでは、すべての Delphi コンパイラでサポートされる、インターフェイスの参照カウントについて説明します。
Delphi コンパイラは、インターフェイスのクエリと参照カウントの実装を通じて、IInterface メモリ管理のほとんどを提供しています。そのため、インターフェイスによって生成/破壊されるオブジェクトを持っている場合、TInterfacedObject から派生することで参照カウントを簡単に使用できます。参照カウントを使用する場合は、オブジェクトをインターフェイス参照としてのみ保持し、参照カウントの一貫性を保つように注意する必要があります。例:
procedure beep(x: ITest); function test_func() var y: ITest; begin y := TTest.Create; // because y is of type ITest, the reference count is one beep(y); // the act of calling the beep function increments the reference count // and then decrements it when it returns y.something; // object is still here with a reference count of one end;
これは、最も簡潔で安全なメモリ管理アプローチで、TInterfacedObject を使用する場合は、自動的に処理されます。このルールに従わない場合、次のコードに示すように、オブジェクトが予期せず消滅してしまうおそれがあります。
function test_func() var x: TTest; begin x := TTest.Create; // no count on the object yet beep(x as ITest); // count is incremented by the act of calling beep // and decremented when it returns x.something; // surprise, the object is gone end;
メモ: 上記の例では、beep 手続きは、宣言通りに、パラメータの参照カウントをインクリメントさせます(_AddRef 呼び出し)。これに対し、次の宣言はどちらもどうではありません:
procedure beep(const x: ITest);
または
procedure beep(var x: ITest);これらの宣言の場合、生成されるコードはより小さく高速です。
一貫して適用できないために参照カウントを使用できないケースの 1 つは、オブジェクトがコンポーネントであるか、別のコンポーネントが所有するコントロールである場合です。その場合でもインターフェイスを使用できますが、オブジェクトの有効期間はそのインターフェイスによって決まるわけではないため参照カウントは使用しないでください。