我是否可以在不释放它们的情况下抛弃class
es,或者我的软件是否会开始泄漏泄漏?
例如,我可以这样做吗
Engine := TEngine.Create(TV);
然后没有任何问题摆脱引用,或者我必须先调用它的Free
方法吗?
或者有一个函数返回TSomething
而不必在以后释放它的引用?
答案 0 :(得分:2)
一般规则是,如果你创建它,你应该释放它。最好的方法是尝试..如果你在代码中创建它:
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 :(得分: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的实现将自动调用析构函数。