如何使用记录列表

时间:2019-05-12 12:02:30

标签: delphi

我在方法中有一条记录作为局部变量。然后,将其添加到属于该类的TList中。现在我的问题是方法完成后,记录仍然有效吗? (或其已损坏,我不应该使用MyList.List [0])。 这是一个示例代码:

TTestClass = class
  MyList: TList<TMyRec>;
  procedure add;
end;

procedure TTestClass.add;
var
  ARec: TMyRec;
begin
  Arec.a:= 100;
  ARec.b:= 'abc';

  MyList.add(ARec);
end;

1 个答案:

答案 0 :(得分:2)

  

记录仍然有效吗?

,但其是。

记录是在堆栈上分配的值类型,这意味着它们通过值传递(在每个分配中复制)

像以前一样使用它们时,实际上是在执行从本地变量到列表中存储的隐式副本。

因此,在方法完成执行后,var块中声明的记录无效。但是它的值已经被复制到列表的存储中,因此它是有效值。

考虑以下代码以获得更多说明:

program Project20;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, system.generics.collections;

type
  PMyRec = ^TMyRec;
  TMyRec = record
    a: Integer;
    b: string;
  end;

  TTestClass = class
    MyListOfPointers: TList<PMyRec>;
    MyListOfValues: TList<TMyRec>;

    constructor Create;
    destructor Destroy; override;
    procedure add;
    procedure addP;
    procedure ShowRecs;
  end;


  procedure TTestClass.add;
  var
    ARec: TMyRec;
  begin
    Arec.a:= 100;
    ARec.b:= 'abc';

    MyListOfValues.add(ARec);
  end;

  procedure TTestClass.addP;
  var
    ARec: TMyRec;
  begin
    Arec.a:= 100;
    ARec.b:= 'abc';

    MyListOfPointers.add(@ARec);
  end;

  constructor TTestClass.Create;
  begin
    MyListOfPointers := TList<PMyRec>.Create;
    MyListOfValues := TList<TMyRec>.Create;
  end;

  destructor TTestClass.Destroy;
  begin
    MyListOfPointers.Free;
    MyListOfValues.Free;
    inherited;
  end;

  procedure TTestClass.ShowRecs;
  begin
    writeln(PMyRec(MyListOfPointers[0])^.b + ' ' + PMyRec(MyListOfPointers[0])^.a.ToString);
    writeln(MyListOfValues[0].b + ' ' + MyListOfValues[0].a.ToString);
  end;

var
  MyClass: TTestClass;

begin
  try
    MyClass := TTestClass.Create;
    try
      MyClass.Add;
      MyClass.AddP;
      MyClass.ShowRecs;

    finally
      MyClass.Free;
    end;

    Readln;
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
      Readln;
    end;
  end;
end.

输出为

第一次尝试

39866256
abc 100

第二次尝试

40390544
abc 100

您不会遇到访问冲突,但是唯一行为a将对该地址使用任何值,而b始终为空(b = ''),因为它是托管的类型。