8

アプリケーション全体で広く使用されるヘルパークラスがあります。実装はインターフェイス参照カウントに依存しています。考え方は大まかに次のとおりです。

...
var
  lHelper: IMyHelper;
begin
  lHelper := TMyHelper.Create(some params);
  ...some code that doesn't have to access lHelper
end;

したがって、実装は、メソッドの最後でスコープ外になるIMyHelperに依存しますが、前ではありません。

それで、質問しているのは、変数がメソッドの残りの部分でアクセスされない場合、将来のDelphiコンパイラがスマートに再生されず、作成された直後にインターフェイスを解放しないことを確信できますか?

4

2 に答える 2

10

私見あなたはそれを確信することができます。範囲外のパターンは、おそらくこのメソッドの命令ブロックに対してグローバルのままになります。これは重大な変更になります。

Barry Kelly (Embarcaderoから)からのこのコメントを参照してください:

以前のコメントに関して、明示的変数について:インターフェイス変数の使用を最適化した仮想の(そして破壊的な変更)ケースでは、説明されているRAIIのような機能だけでなく、明示的な変数のアプローチも破壊する可能性があります。FooNotifierとBarNotifierに割り当てられた値は使用されないため、「理論的には」それらはより早く解放され、同じストレージを再利用する可能性さえあります。

しかしもちろん、インターフェースの破壊は副作用をもたらす可能性があり、それが投稿の効果に依存しているものです。このような副作用が目に見える変化をもたらすように言語を変更することは、私たちが喜んで行うことではありません。

したがって、Embarcaderoはここで下位互換性の変更を導入しないと推測できます。インターフェイスメモリを再利用することの利点は、互換性を壊して副作用をもたらす価値はありません。特にスタックがすでに割り当てられ、整列されている場合(x64モデルはx86より多くのスタック)。

ガベージコレクターがその言語に導入された場合にのみ(私は個人的な観点からは望んでいません)、オブジェクトの寿命が変わる可能性があります。ただし、この場合、寿命はおそらく長くなる可能性があります。

いずれの場合も、独自のコードを作成して、メソッドの最後に確実にリリースされるようにすることができます。

var
  lHelper: IMyHelper;
begin
  lHelper := TMyHelper.Create(some params);
  try 
    ...some code that doesn't have to access lHelper
  finally
    lHelper := nil; // release the interface count by yourself
  end;
end;

実際、これはコンパイラーによってすでに生成されたコードです。これを書くことは完全に冗長になりますが、コンパイラがあなたをだまさないことを保証します。

インターフェイスと参照カウントについて話すときは、Delphiでの循環参照の潜在的な問題を考慮に入れてください。インターフェイスの循環参照のための「弱いポインタ」の必要性については、このすばらしい記事(つまり「例2-15」)を参照してください。

他の言語(JavaやC#など)は、ガベージコレクターを使用してこれを解決します。Objective Cは、明示的な「弱ポインタ​​のゼロ化」メカニズムを使用してそれを解決します。実装の可能性については、この説明またはこのSOの回答を参照してください。おそらく、Delphiの将来のバージョンでは、Objective Cで導入されたARCモデルと同様の実装の使用を検討する可能性があります。しかし、既存のコードとの互換性を維持するための明示的な構文があると思います。

于 2012-02-01T09:50:57.323 に答える
4

ドキュメントにはこれが記載されています(私の強調):

Win32プラットフォームでは、インターフェイス参照は通常、参照カウントによって管理されます。これは、System/IInterfaceから継承された_AddRefメソッドと_Releaseメソッドに依存します。参照カウントのデフォルトの実装を使用すると、オブジェクトがインターフェイスを介してのみ参照される場合、手動でオブジェクトを破棄する必要はありません。オブジェクトへの最後の参照がスコープ外になると、オブジェクトは自動的に破棄されます。

ローカル変数のスコープはメソッドであるため、現在の仕様では_Release、メソッドが完了するまで呼び出されません。

将来的に仕様が変更されないという約束はありませんが、言語のこの部分に変更が加えられる可能性はほとんどないと思います。

于 2012-02-01T09:54:42.350 に答える