0

我可以在class不释放它们的情况下扔掉 es,还是我的软件会开始泄漏?

例如我可以这样做吗

Engine := TEngine.Create(TV);

然后摆脱引用没有任何问题,还是我必须先调用它的Free方法?

或者有一个返回 aTSomething而不必稍后释放它的引用的函数?

4

2 回答 2

2

一般规则是,如果你创建它,你应该释放它。最好的方法是尝试..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 的析构函数中释放 ObjectList 或 ObjectDictionary,在 TInterfacedObject 中使用 TObjectList 或 TObjectDictionary 就不必再担心垃圾回收了。当 referenceCount=0 时,Delph 的实现将自动调用该析构函数。

于 2013-04-14T05:30:26.383 回答