"复制"不会创建动态阵列的独立副本

jaa*_*wer 2 arrays delphi

参考http://docwiki.embarcadero.com/RADStudio/XE6/en/Structured_Types#Dynamic_Arrays上的在线文档.

很清楚地写道,要创建动态数组的独立副本,请使用Copy()函数.在该链接中找到的示例代码还说明了在复制之后,如果更改了一个数组,则它不会反映到另一个数组中,因为它们都是独立副本.但是,这对我不起作用.复制之后,如果我更改了一个数组,另一个数组会自动更改为接收相同的值,这意味着Copy()只执行X:= Y所做的操作.根据文档,"X:= Y"和"X:=复制(Y)" 相同.

这是我的代码:

type
  TTestArray = array of TMyType; //Note: TMyType is a class and not a record.

var
  X, Y, Z: TTestArray;

begin
  SetLength(X, 1); //create first array
  X[0].testString := 'Test Y';
  Y := copy(X);
  X[0].testString := 'Test Z'; //re-assign another value
  Z := copy(X);
  X[0].testString := 'Test X';
Run Code Online (Sandbox Code Playgroud)

此时,testString字段应包含不同的文本.所以,

X[0].testString should be 'Test X'
Y[0].testString should be 'Test Y'
Z[0].testString should be 'Test Z'
Run Code Online (Sandbox Code Playgroud)

但是,所有这三个都只有'Test X'作为testString中的值,因此暗示Copy()没有创建数组X的独立副本.相反,所有三个数组都指向相同的内存位置.

任何可靠地创建动态数组的独立副本的方法(即完成我上面尝试做的事情)?

注意(稍后添加): TMyType是一个类而不是记录.因此,根据下面非常有用的评论,这是CLASS情况下的预期行为.那么,在这种情况下,如何将X独立复制到Y和Z?

注2:从主题行中删除"Bug".对不起,Embarcadero ......

注3: TMyType必须是一个类.我无法控制它.它是从Web服务定义(WSDL)创建的,它公开了PeopleSoft的一些功能.

Joh*_*ica 9

问题是你定义TMyType为:

type
  TMyType = class(SomeObject)
  ....
  public
    testString: string;
  end;
Run Code Online (Sandbox Code Playgroud)

创建初始化时TestArray,它不会填充对象本身,而只是指向这些对象的指针.

发生了什么......
数组看起来像这样:

Array           contents of array     contents of the heap
-------------+----------------------+-----------------------
X[0]         |-> pointer_to_MyType1 |-> MyType1
X[1]         |-> pointer_to_MyType2 |-> MyType2
Run Code Online (Sandbox Code Playgroud)

复制数组时,会发生以下情况:

Array           contents of array            contents of the heap
-------------+------------------------------+-----------------------
Y[0]         |-> copy_of_pointer_to_MyType1 |-> MyType1
Y[1]         |-> copy_of_pointer_to_MyType2 |-> MyType2
Run Code Online (Sandbox Code Playgroud)

你想看到
什么......这是你期望发生的事情:

Array           contents of array            
-------------+-------------------
X[0] or Y[0] |-> (copy of)MyType1
X[0] or Y[0] |-> (copy of)MyType2
Run Code Online (Sandbox Code Playgroud)

如何实现这一点
但是为了实现这一点,你必须定义TMyType为:

type
  TMyType = record
  public
    TestString: string;
  end;
Run Code Online (Sandbox Code Playgroud)

现在,记录本身将存储在数组中,而不是指向存储在别处的数据的指针.

在这种情况下,如何将X独立复制到Y和Z?

如果你想保留类的使用,那么你必须编写自己的版本Copy; 就像是:

uses
  System.SysUtils, system.classes, Generics.Collections;

type
  TMyList<T: TPersistent, constructor > = class(TList<T>)
  public
    function CloneArray: TMyList<T>;
  end;

implementation

function TMyList<T>.CloneArray: TMyList<T>;
var
  i: integer;
  temp: T;
begin
  Result:= TMyList<T>.Create;
  for i:= 0 to SizeOf(self) -1 do begin
    temp:= T.Create;
    temp.assign(self.items[i]);
    Result.Add(temp);
  end; {for i}
end;
Run Code Online (Sandbox Code Playgroud)

显然,上面的代码假设您可以使用无参数构造函数.

另请参见:正确复制Delphi对象的方法