首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi类TList

Delphi类TList
EN

Stack Overflow用户
提问于 2018-06-13 06:14:17
回答 1查看 452关注 0票数 4

我已经创建了一个简单的类,我将对象保存在一个泛型列表中。我设法让它起作用了。但我不明白为何这是行不通的。

代码语言:javascript
复制
for Monster in MonsterList do
    begin
      Monster.Free;
      MonsterList.Remove(Monster);
    end;

如果我尝试从MonsterList中释放并删除这样的项目,它并不真正删除,在我的例子中,名称消失了,但是强度值仍然在那里。如果之后我试图列出MonsterList的内容,我总是只剩下一项。所以我谷歌了一下,在Stack溢出网站上发现,我的好解决方案就是简单地计算下来。

另一件事是,当我将怪兽添加到MonsterList中时,我添加了3个条目,但是如果我调试,我看到MonsterList实际上有0,1,2,3 3是空--只有当我添加所有三个对象时,如果我只添加两个对象,它不会创建最终的空指针。这是某种形式的优化吗?

整个守则(不多)

代码语言:javascript
复制
unit MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Generics.Collections, Generics.Defaults,
  System.Types;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMonster = class
    private
      fName : string;
      fStrength : integer;
      fisDead : boolean;
    public
      constructor Create(Name : string; Strength : integer);
      destructor Destroy; override;

      property Name : string read fName write fName;
      property Strength : integer read fStrength write fStrength;
      property isDead : boolean read fisDead write fisDead;
  end;

var
  Form1: TForm1;
  MonsterList : TList<TMonster>;
  MonsterInstances : integer = 0;


implementation

{$R *.dfm}

constructor TMonster.Create(Name: string; Strength: integer);
begin

  inc(MonsterInstances);

  fName := Name;
  fStrength := Strength;
  fisDead := false;
end;

destructor TMonster.Destroy;
begin
  dec(MonsterInstances);

  inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Monster : TMonster;
    i : integer;
begin
  MonsterList := TList<TMonster>.Create;

  Memo2.Lines.Add(inttostr(MonsterInstances));

  MonsterList.Add(TMonster.Create('Jill',10));
  MonsterList.Add(TMonster.Create('Jane',1));
  MonsterList.Add(TMonster.Create('Rob',20));

  Memo2.Lines.Add(inttostr(MonsterInstances));

  for Monster in MonsterList do
    begin
      Memo1.Lines.Add(Monster.fName+ ' Strenght '+inttostr(Monster.fStrength)+' IsDead= '+booltostr(Monster.fisDead))
    end;

  MonsterList[1].isDead:=true;

  // not working
  {for Monster in MonsterList do
    begin
      Monster.Free;
      MonsterList.Remove(Monster);
    end; }

  // works
  for i := MonsterList.Count-1 downto 0 do
    begin
      if MonsterList[i].isDead = true then
        begin
          MonsterList[i].Free;
          MonsterList.Delete(i);
          MonsterList.Capacity:=MonsterList.Capacity-1;
        end;
    end;

  Memo1.Lines.Add('Survivors :');

  for Monster in MonsterList do
    Memo1.Lines.Add(Monster.Name+' Strenght '+inttostr(Monster.Strength));


  ShowMessage(inttostr(MonsterInstances));

end;

end.

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-13 06:35:34

您不能在这样迭代列表的同时修改它。相反,释放所有成员,然后清除列表。

代码语言:javascript
复制
for Monster in MonsterList do
  Monster.Free;
MonsterList.Clear;

这有一个额外的优点,即不调用Remove,因为它会花费时间搜索该项。

也许更简单的做法是使用TObjectList<T>并允许集合管理其成员的生存期。然后只需调用Clear,只要OwnsObjectsTrue,所有成员都将被销毁,列表将被清除。

就第二个问题而言,如果添加三个项,则有索引0、1和2的项。没有索引3的项。现在,集合内部很可能使用一个内部数组,该数组分配过多。所以私有内部数组可以有一个索引3,但是这个内部数组的内容对你来说并不重要。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50830198

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档