Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 包含动态数组的记录的常规列表_Arrays_Delphi_Generics_Record_Tlist - Fatal编程技术网

Arrays 包含动态数组的记录的常规列表

Arrays 包含动态数组的记录的常规列表,arrays,delphi,generics,record,tlist,Arrays,Delphi,Generics,Record,Tlist,我有一个通用的记录列表。这些记录包含一个动态数组,如下所示 Type TMyRec=record MyArr:Array of Integer; Name: string; Completed: Boolean; end; var MyList:TList<TMyRec>; MyRec:TMyRec; 将第一个项目添加到列表后,MyRec.MyArr更改时,存储到列表中的MyArr也会更改。但是,其他记录字段没有 我的问题是如何防止MyRec.My

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

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

var
  MyList:TList<TMyRec>;
  MyRec:TMyRec;
将第一个项目添加到列表后,
MyRec.MyArr
更改时,存储到列表中的
MyArr
也会更改。但是,其他记录字段没有

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


是否需要声明多个记录。

此示例可以简化为这样,删除对泛型的所有引用:

{$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.
输出为:

42 666 输出:

42 42 [0]的值为2。(如果A和B是静态数组,则A[0]将 仍然是1。)分配给动态数组索引(例如, MyFlexibleArray[2]:=7)不重新分配数组。超出范围 在编译时不报告索引。相比之下,作出 动态数组的独立副本,必须使用全局副本 功能:

 var
   A, B: array of Integer;
 begin
   SetLength(A, 1);
   A[0] := 1;
   B := Copy(A);
   B[0] := 2; { B[0] <> A[0] }
 end;
var
A、 B:整数数组;
开始
设定长度(A,1);
A[0]:=1;
B:=副本(A);
B[0]:=2;{B[0]A[0]}
结束;
…以下是对原始问题争议的观察

至于其余的,我更喜欢在你添加值后立即断开变量和列表之间的链接。几个月后,你会忘记你的问题,也许会重构你的程序。如果将第二个
SetLength
放在
列表之外。添加
,您可能会忘记该记录仍然包含对列表中相同数组的引用

  TMyRec=record
    MyArr: TArray< double >; // making it 1D for simplicity
    Name: string;
    Completed: Boolean;
  end;


SetLength(MyRec.MyArr,5);
MyRec.MyArr[0]:=8;  // just for demonstration
MyRec.Name:='Record 1';
MyRec.Completed:=true;
MyList.Add(MyRec);
MyRec.MyArr := nil; // breaking the parasite link immediately!
现在,最后一个选项是将使用的代码压缩成一个过程,您可以多次调用该过程。然后变量将变成本地变量,Delphi将自动为您完成它

Procedure AddRec( const Name: string; const Compl: boolean; const Data: array of double);
var i: integer; MyRec: TMyRec;
begin
  SetLength(MyRec.MyArr, Length( Data ) );
  for i := 0 to Length(Data) - 1 do
    MyRec.MyArr[i] := Data [i];  

  MyRec.Name := Name;

  MyRec.Completed := Compl;
  MyList.Add(MyRec);
end;

MyList:=TMyList<TMyRec>.create;

AddRec( 'Record 1', True , [ 8 ]);
AddRec( 'Record 2', False, [ 5 ]);
...
Procedure AddRec(常量名称:string;常量Compl:boolean;常量数据:double数组);
varⅠ:整数;MyRec:TMyRec;
开始
设置长度(MyRec.MyArr,长度(数据));
对于i:=0到长度(数据)-1 do
MyRec.MyArr[i]:=数据[i];
MyRec.Name:=名称;
MyRec.Completed:=完成的组件;
MyList.Add(MyRec);
结束;
MyList:=TMyList.create;
AddRec('Record 1',True[8]);
AddRec('Record 2',False,[5]);
...

由于
MyRec
现在是一个局部变量,它在退出
AddRec
时会被破坏,它不会保留到数组的链接,也不会影响您或任何其他使用您的类型的开发人员。

只需在旧变量中创建一个新变量,一切都应该正常

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);

MyRec := TMyRec.Create();
SetLength(MyRec.MyArr,5);

MyRec.MyArr[0]:=5;  // just for demonstration
MyRec.Name:='Record 2';
MyRec.Completed:=false;
MyList.Add(MyRec);
MyList:=TList.Create;
设定长度(MyRec.MyArr,5);
MyRec.MyArr[0]:=8;//只是为了示范
MyRec.Name:=“记录1”;
MyRec.Completed:=真;
MyList.Add(MyRec);
MyRec:=TMyRec.Create();
设定长度(MyRec.MyArr,5);
MyRec.MyArr[0]:=5;//只是为了示范
MyRec.Name:=“记录2”;
MyRec.Completed:=false;
MyList.Add(MyRec);

我刚修好了question@DavidHeffernan但你不知道这个话题的真正含义。这两个部分相互矛盾,你自己决定哪一个是错的。我认为这是值得的,如果他放弃堆栈溢出,那么让这个问题对任何人有利,而不是对逃跑的TS有利是有意义的。但是TS在这里,他可以按照他真正的意图解决这个问题。这是我的错误
MyArr:整数数组
是正确的偏差。问题被修改为David@DavidHeffernan你能在答案中加上零、最终和局部风险值吗?那我的就可以了deleted@DavidHeffernan嗯,提到他们“他们存在”并不是在举例说明利弊。不能同意你已经做了:-)甚至没有提到本地变量。也没有立即中断链接。+1,我很好奇为什么没有直接的语言元素来进行深度复制
Clone()
是个好名字。或者介绍COW动态数组(我已经有了)。@LURD深度复制是一件很容易说,但很难做的事情。在语言级别上,您需要每种类型都能够执行深度复制。这对指针意味着什么?也许类型化指针是可行的,但非类型化指针呢?如何深度复制接口?所以我认为它本质上是硬的。谢谢你的紫外线顺便说一句。我必须说,在这里投票很奇怪。更多人投票支持非答案。@lurd可能是因为字符串由简单字符组成,但数组可以由对象、接口和谁知道是什么组成。它将隐藏导致失败期望的复杂性,比如本主题开头的期望。对于字符串、接口等,只需增加引用计数。未类型化的指针将保留在野外,但与Copy()命令没有区别。@alcalde Python类型确实需要实现钩子才能使deepcopy工作。钩子定义得很好,但它们需要演员的合作。它没有创建方法。没有解释的答案永远都不理想。编程应该是理解而不是魔法咒语。
 var
   A, B: array of Integer;
   begin
     SetLength(A, 1);
     A[0] := 1;
     B := A;
     B[0] := 2;
   end;
 var
   A, B: array of Integer;
 begin
   SetLength(A, 1);
   A[0] := 1;
   B := Copy(A);
   B[0] := 2; { B[0] <> A[0] }
 end;
  TMyRec=record
    MyArr: TArray< double >; // making it 1D for simplicity
    Name: string;
    Completed: Boolean;
  end;


SetLength(MyRec.MyArr,5);
MyRec.MyArr[0]:=8;  // just for demonstration
MyRec.Name:='Record 1';
MyRec.Completed:=true;
MyList.Add(MyRec);
MyRec.MyArr := nil; // breaking the parasite link immediately!
SetLength(MyRec.MyArr,5);
MyRec.MyArr[0]:=8;  // just for demonstration
MyRec.Name:='Record 1';
MyRec.Completed:=true;
MyList.Add(MyRec);
Finalyze(MyRec); // breaking all the parasite links immediately!
Procedure AddRec( const Name: string; const Compl: boolean; const Data: array of double);
var i: integer; MyRec: TMyRec;
begin
  SetLength(MyRec.MyArr, Length( Data ) );
  for i := 0 to Length(Data) - 1 do
    MyRec.MyArr[i] := Data [i];  

  MyRec.Name := Name;

  MyRec.Completed := Compl;
  MyList.Add(MyRec);
end;

MyList:=TMyList<TMyRec>.create;

AddRec( 'Record 1', True , [ 8 ]);
AddRec( 'Record 2', False, [ 5 ]);
...
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);

MyRec := TMyRec.Create();
SetLength(MyRec.MyArr,5);

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