我在方法中有一条记录作为局部变量。然后,将其添加到属于该类的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;
答案 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 = ''
),因为它是托管的类型。