当前位置:  开发笔记 > 前端 > 正文

递归析构函数

如何解决《递归析构函数》经验,为你挑选了1个好方法。

我有以下两个类:

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;
  FTest: TList;
public
  constructor Create(AName: string);
  destructor Destoroy();
  property Name: string read FName;
  property ItemProps: TList read FProps write FProps;
  property Test: TList read FTest write FTest;
end;

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

constructor TTest.Create(AName: string);
begin
  Self.FName := AName;
  Self.FProps := TList.Create();
  Self.FTest := TList.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;

问题是这段代码泄露了内存.我应该如何重写析构函数以修复内存泄漏?



1> David Heffer..:

第一个问题在这里:

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 read FProps;
property Test: TList read FTest;

如果任何正文试图写入这些属性,您的代码将导致泄漏.

您是否可以使用TObjectList而不是TList将生命周期管理委托给列表类.这往往会导致更简单的代码.

TList实例公开为公共属性确实会使您的类暴露于滥用状态.此类的客户端可以调用该类的任何公共方法,并可能以您不期望的方式改变列表,并且不希望满足.您应该寻求更多地封装这些对象.

作为一般规则,您应始终调用类的继承构造函数.在你的情况下,构造函数是TObject什么都不做的构造函数.但是,最好还是调用它.这样做意味着如果您以后更改继承层次结构,则不会因未调用新父类的构造函数而陷入困境.

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

Self到处都在使用.这很好,但它根本不是惯用的.我建议你不要这样做,否则你的代码会非常冗长,不易阅读.

您发布的代码中存在大量错误.您的程序中显然有更多未发布的代码.我非常希望代码也包含错误,所以如果在应用上述所有更改后仍然存在泄漏,请不要感到惊讶.

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有