gpt4 book ai didi

arrays - 包含动态数组的通用记录列表

转载 作者:行者123 更新时间:2023-12-03 15:23:29 25 4
gpt4 key购买 nike

我有一个通用的记录列表。这些记录包含一个动态数组,如下所示

Type
TMyRec=record
MyArr:Array of Integer;
Name: string;
Completed: Boolean;
end;

var
MyList:TList<TMyRec>;
MyRec:TMyRec;

然后我创建列表并设置数组长度,如下所示

MyList:=TList<TMyRec>.Create;
SetLength(MyRec.MyArr,5);
MyRec.MyArr[0]:=8; // just for demonstration
MyRec.Name:='Record 1';
MyRec.Completed:=true;
MyList.Add(MyRec);

然后我更改 MyArr 中的数据,还更改 MyRec.Name 并向列表中添加另一个项目

MyRec.MyArr[0]:=5;  // just for demonstration
MyRec.Name:='Record 2';
MyRec.Completed:=false;
MyList.Add(MyRec);

当将第一项添加到列表后 MyRec.MyArr 发生变化时,存储到列表中的 MyArr 也会发生变化。但其他记录字段则不然。

我的问题是如何防止 MyRec.MyArr 中的更改反射(reflect)在已存储在列表项中的数组上。

我需要声明多条记录吗?

最佳答案

这个例子可以像这样简化,删除所有对泛型的引用:

{$APPTYPE CONSOLE}

var
x, y: array of Integer;

begin
SetLength(x, 1);
x[0] := 42;
y := x;
Writeln(x[0]);
y[0] := 666;
Writeln(x[0]);
end.

输出为:

42666

The reason for this is that a dynamic array is a reference type. When you assign to a variable of dynamic array type, you are taking another reference and not making a copy.

You can resolve this by forcing a reference to be unique (that is have just a simple reference). There are a number of ways to achieve this. For instance, you can call SetLength on the array that you want to be unique.

{$APPTYPE CONSOLE}

var
x, y: array of Integer;

begin
SetLength(x, 1);
x[0] := 42;
y := x;
SetLength(y, Length(y));
Writeln(x[0]);
y[0] := 666;
Writeln(x[0]);
end.

输出:

4242

So, in your code you can write it like this:

MyList:=TList<TMyRec>.Create;

SetLength(MyRec.MyArr,5);
MyRec.MyArr[0]:=8; // just for demonstration
MyRec.Name:='Record 1';
MyRec.Completed:=true;
MyList.Add(MyRec);

SetLength(MyRec.MyArr,5); // <-- make the array unique
MyRec.MyArr[0]:=5; // just for demonstration
MyRec.Name:='Record 2';
MyRec.Completed:=false;
MyList.Add(MyRec);

您可以使用各种其他方式来强制唯一性,包括Finalize、分配nilCopy等。

documentation 中详细介绍了此问题。 。以下是相关摘录:

If X and Y are variables of the same dynamic-array type, X := Y points X to the same array as Y. (There is no need to allocate memory for X before performing this operation.) Unlike strings and static arrays, copy-on-write is not employed for dynamic arrays, so they are not automatically copied before they are written to. For example, after this code executes:

 var
A, B: array of Integer;
begin
SetLength(A, 1);
A[0] := 1;
B := A;
B[0] := 2;
end;

the value of A[0] is 2. (If A and B were static arrays, A[0] would still be 1.) Assigning to a dynamic-array index (for example, MyFlexibleArray[2] := 7) does not reallocate the array. Out-of-range indexes are not reported at compile time. In contrast, to make an independent copy of a dynamic array, you must use the global Copy function:

 var
A, B: array of Integer;
begin
SetLength(A, 1);
A[0] := 1;
B := Copy(A);
B[0] := 2; { B[0] <> A[0] }
end;

关于arrays - 包含动态数组的通用记录列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21483495/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com