それらを解放せずに esを放り投げることはできますclass
か? それとも、ソフトウェアがリークを吐き出し始めますか?
たとえば、私はこれを行うことができます
Engine := TEngine.Create(TV);
次に、問題なく参照を取り除きますか、それともFree
最初にそのメソッドを呼び出す必要がありますか?
または、を返す関数があり、TSomething
後でその参照を解放する必要はありませんか?
それらを解放せずに esを放り投げることはできますclass
か? それとも、ソフトウェアがリークを吐き出し始めますか?
たとえば、私はこれを行うことができます
Engine := TEngine.Create(TV);
次に、問題なく参照を取り除きますか、それともFree
最初にそのメソッドを呼び出す必要がありますか?
または、を返す関数があり、TSomething
後でその参照を解放する必要はありませんか?
原則として、作成した場合は解放する必要があります。最善の方法は、コードで作成している場合は 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;
技術的にはい、コンストラクターで初期化するものはすべて明示的に解放する必要があります。
ただし、適切に使用すると、ほとんどの問題を回避できる簡単な回避策がいくつかあります。
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 の実装によって自動的に呼び出されます。