0

それらを解放せずに esを放り投げることはできますclassか? それとも、ソフトウェアがリークを吐き出し始めますか?

たとえば、私はこれを行うことができます

Engine := TEngine.Create(TV);

次に、問題なく参照を取り除きますか、それともFree最初にそのメソッドを呼び出す必要がありますか?

または、を返す関数があり、TSomething後でその参照を解放する必要はありませんか?

4

2 に答える 2

2

原則として、作成した場合は解放する必要があります。最善の方法は、コードで作成している場合は try..finally です。

var
  Engine: TEngine;
begin
  Engine := TEngine.Create(TV);
  try
    // Do stuff with Engine
  finally
    Engine.Free;
  end;
end;

これに対する例外は、所有者をパラメーターとして受け入れるオブジェクトがある場合です ( のようなビジュアル コントロールTEditや非ビジュアルな子孫などTComponent)。所有者を割り当てると、所有者が解放されると解放されます。(所有者なしで作成した場合でも、自分で解放する必要があります。)

procedure TForm1.FormCreate(Sender: TObject);
var
  EditA, EditB: TEdit;
begin
  EditA := TEdit.Create(Self);  // You're passing the form as owner; don't free
  EditB := TEdit.Create(nil);   // Creating without an owner; you free.
end;

クラスが別のオブジェクトのメンバー (フィールド) である場合は、それを含むオブジェクトで作成しconstructor、その で解放しますdestructor

type
  TOuterClass = class(TObject)
  private
    FEngine: TEngine;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

constructor TOuterClass.Create;
begin
  inherited;
  FEngine := TEngine.Create(TV);
end;

destructor TOuterClass.Destroy;
begin
  FEngine.Free;
  inherited;
end;
于 2013-04-13T23:39:30.263 に答える
1

技術的にはい、コンストラクターで初期化するものはすべて明示的に解放する必要があります。

ただし、適切に使用すると、ほとんどの問題を回避できる簡単な回避策がいくつかあります。

1: TInterfacedObject を使用します。

  IMyStuff = interface(IUnknown)
    ['{9DF82155-2475-4403-8933-969DC4912AD7}']
    function Print:boolean;
    procedure DoStuff;
  end;

  TMyStuff = class(TInterfacedObject, IMyStuff)
    private
      function Print:boolean;
      procedure DoStuff;
   end;

他のクラスと同様に TMyStuff を実装します。ただし、コードでそのクラスを使用する場合は、次のように IMyStuff 型の変数を使用します。

procedure MyIProcedure;
var myStuff: IMyStuff;
begin

   myStuff:=TMyStuff.create;
   myStuff.DoStuff;

end;

'TMyStuff.create' 呼び出しでキャストする必要はありません (この場合 - 場合によっては...) - 変数は IMystuff 型であるため、これは暗黙的です。IMyStuff を解放する必要はありません (実際にはできませんが、IMyStuff:=nil を呼び出すことはできます)。インターフェイス タイプとして宣言されているため、COM 参照カウント モデルを使用して自動化されたガベージ コレクションが実装されます。Delphi がこれを処理します。 TInterfacedObject から継承する場合。

ただし、クラス型変数を混在させないでください。つまり、TMyStuff と IMyStuff 変数型を混在させないでくださいこれは、厄介な混乱やエラーにつながる可能性があり、頭を悩ませることになります。これが、ここで行ったように、一般的に TInterfacedObject のメンバーをPRIVATEとして宣言し、TMyStuff への参照を介してアクセスできないようにする理由です。ただし、IMyStuff への参照を介してアクセスできます。定義により、すべてのインターフェイス メンバーはパブリックです。

2: Ken の優れた回答に加えて、VCL の TObjectList と TObjectDictionary は、含まれるすべてのオブジェクト参照に対して自動化されたガベージ コレクションを提供します (詳細については、Delphi のドキュメントを参照してください)。

TInterfacedObject で TObjectList または TObjectDictionary を使用すると、TInterfacedObject のデストラクタで ObjectList または ObjectDictionary を解放する限り、ガベージ コレクションの心配をする必要がなくなります。referenceCount=0 の場合、そのデストラクタは Delph の実装によって自動的に呼び出されます。

于 2013-04-14T05:30:26.383 に答える