递归析构函数

bob_saginowski

我有以下两节课:

type
  TItemProp = class
  private
    FItemPropName: string;
    FItemPropValue: string;
  public
    constructor Create(AItemPropName, AItemPropValue: string);
    class function GetItemProp(AHTMLElement: OleVariant; AProp: string): TItemProp;
    property ItemPropName: string read FItemPropName;
    property ItemPropValue: string read FItemPropValue;
 end;

TTest = class
private
  FName: string;
  FProps: TList<TItemProp>;
  FTest: TList<TTest>;
public
  constructor Create(AName: string);
  destructor Destoroy();
  property Name: string read FName;
  property ItemProps: TList<TItemProp> read FProps write FProps;
  property Test: TList<TTest> read FTest write FTest;
end;

这是TTest类的构造函数和析构函数的代码:

constructor TTest.Create(AName: string);
begin
  Self.FName := AName;
  Self.FProps := TList<TItemProp>.Create();
  Self.FTest := TList<TTest>.Create();
end;

destructor TTest.Destoroy();
var
  I: Integer;
begin
  for I := 0 to Self.FTest.Count - 1 do
  begin
    Self.FTest[I].Free;
    Self.FTest[I] := nil;
  end;

  Self.FProps.Free;
  Self.FTest.TrimExcess;
  Self.FTest.Free;
  inherited; 
end;

问题在于此代码正在泄漏内存。我应该如何重写析构函数以修复内存泄漏?

大卫·赫弗南(David Heffernan)

第一个问题在这里:

destructor Destroy();

您需要覆盖在中声明的虚拟析构函数TObject像这样:

destructor Destroy; override;

您的析构函数实现不必要地复杂,并且也不会破坏所拥有的对象FProps这个析构函数应该这样写:

destructor TTest.Destroy;
var
  I: Integer;
begin
  for I := 0 to FTest.Count - 1 do
    FTest[I].Free;
  FTest.Free;

  for I := 0 to FProps.Count - 1 do
    FProps[I].Free;
  FProps.Free;

  inherited; 
end;

公开这些列表对象的属性不应具有setter方法。因此,它们应为只读属性,如下所示:

property ItemProps: TList<TItemProp> read FProps;
property Test: TList<TTest> read FTest;

如果任何人试图写这些属性,您的代码将导致泄漏。

是使用TObjectList而不是TList将生命周期管理委派给列表类。这往往导致更简单的代码。

TList<T>实例公开为公共属性确实会使您的班级遭受滥用。此类的客户端可以调用该类的任何公共方法,并可能以您不希望且不希望满足的方式对列表进行更改。您应该寻求更多封装这些对象的方法。

通常,您应该始终调用类的继承构造函数。在您的情况下,构造函数是TObject什么都不做构造函数。但是,无论如何都称呼它是一个好习惯。这样做意味着如果以后更改继承层次结构,则不会因不调用新父类的构造函数而陷入困境。

constructor TTest.Create(AName: string);
begin
  inherited;
  FName := AName;
  FProps := TList<TItemProp>.Create();
  FTest := TList<TTest>.Create();
end;

Self到处都在使用很好,但这不是惯用语言。我建议您不要养成这种习惯,否则您的代码将非常冗长且不易阅读。

您发布的代码中存在很多错误。程序中显然还有更多代码尚未发布。我非常希望该代码也包含错误,因此即使在应用了所有上述更改之后,如果泄漏仍然存在,也不要感到惊讶。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章