参考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的一些功能.
问题是你定义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对象的方法