在Delphi 7析构函数中如何释放对象数组?

10

假设我的 Delphi 类看起来像这样:

interface
type

    TMySubInfo = class
    public
        Name : string;
        Date : TDateTime;
        Age  : Integer;
    end;

    TMyInfo = class
    public
        Name : string;
        SubInfo : array of TMySubInfo;
        destructor Destroy; override;
    end;

implementation

    destructor TMyInfo.Destroy;
    begin
      // hmmm..
    end;

end.

为了正确地进行清理,析构函数中应该放置什么?只需要执行 SetLength(SubInfo,0) 吗,还是需要循环遍历并释放每个 TMySubInfo ?或者根本不需要做任何事情吗?

8个回答

12

您需要循环遍历并释放每个创建的对象。

您必须知道,声明TMySubInfo数组实际上并不会创建对象。您必须稍后创建它们。

我建议使用TList来实现更加灵活的方法。您甚至可以使用TObjectList,在列表被释放时可以释放所有项目。


是的,我正在循环中调用TMySubInfo.Create来创建它们。但一旦创建,我就不需要添加或删除任何内容 - 这就是为什么我选择了一个简单的数组。 - Blorgbeard
另外,假设我在循环中释放它们,之后我还需要使用SetLength(0)吗? - Blorgbeard
3
无需调用 SetLength。一旦动态数组的引用计数为0,它们就会自动清理。 - Gerry Coll
静态数组怎么处理?如何清理它们? - LostNomad311

11

你应该像这样释放每个项目

destructor TMyInfo.Destroy;
var
  I: Integer;
begin
  for I:= Low(SubInfo) to High(SubInfo) do
   SubInfo[I].Free;
  SetLength(SubInfo, 0); 
  inherited;
end;

6

您需要以与分配相同的方式释放对象。如果您通过调用类的构造函数来分配元素的值,则需要释放该元素引用的对象。

destructor TMyInfo.Destroy;
var
  info: TMySubInfo;
begin
  for info in SubInfo do
    info.Free;
  inherited;
end;

这段代码使用了Delphi 2005中引入的语法。如果你使用的是旧版本,请使用显式循环控制变量:

var
  i: Integer;
begin
  for i := 0 to High(SubInfo) do
    SubInfo[i].Free;

你不需要在最后调用SetLength。像SubInfo这样的动态数组字段会在对象被销毁时自动释放。它与接口、字符串和变量字段的工作方式相同。

5

同意以上所有建议,但我想补充一点(尽管有点过于严谨)的建议:在释放对象时,始终优先使用FreeAndNil()过程而不是Free方法。

迟早会意外访问已经释放的对象。如果你习惯性地对所有东西进行FreeAndNil操作,那么当出现问题时,你就会立即在包含问题的行上得到一个a/v错误。如果你只是Free了对象,那么你很可能会在以后的某个时间遇到神秘的、看似无关的故障...

在这里作为析构函数,这可能看起来有点过分。好吧,有点,但要么无处不FreeAndNil,要么就根本不要这样做。


4

这也是一种分析方法,但与创造过程相反,例如:

For I := List.Count-1 downto 0 do
  List[I].Free;

我认为创建和销毁就像括号(),虽然它实际执行上没有太大区别。Bri


3

如果你是通过构造函数创建对象的话,你需要调用Free方法来释放它们。否则则不需要。


2

每一个新功能都应该有一个免费的版本。


实际上,不是在Delphi中。首先,接口是引用计数的,分配给它们的对象会自动释放。其次,可以使用“Create”初始化记录,但不需要使用“Free”释放它们。 - user

0

Finalize不会释放引用对象或Dispose New的指针等。 - Uli Gerhardt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接