如果您将动态数组作为非 var 参数传递,编译器将进行复制。
下面的小代码示例通过在表单标题中显示 37/42 来证明这一点。
procedure IncArray1(data: array of integer);
var i : integer;
begin
for i := Low(data) to High(data) do
data[i] := data[i] + 5;
end;
procedure IncArray2(var data: array of integer);
var i : integer;
begin
for i := Low(data) to High(data) do
data[i] := data[i] + 5;
end;
procedure TForm8.FormCreate(Sender: TObject);
var
data: array of integer;
begin
SetLength(data, 1);
data[0] := 37;
IncArray1(data);
Caption := IntToStr(data[0]);
IncArray2(data);
Caption := Caption + '/' + IntToStr(data[0]);
end;
如果我们查看生成的汇编代码,IncArray1 以
开头
004552B4 8BCA mov ecx,edx
004552B6 85C9 test ecx,ecx
004552B8 7807 js $004552c1
004552BA 8B1C88 mov ebx,[eax+ecx*4]
004552BD 49 dec ecx
004552BE 53 push ebx
004552BF 79F9 jns $004552ba
004552C1 8BC4 mov eax,esp
此代码将源数组复制到堆栈并将 eax 设置为第一个元素的地址(= 最后一次推送后存储在堆栈指针中的地址)。堆栈向下增长,因此代码从最后一个元素开始(调用 IncArray1 时 edx 包含 High(data))并重复(读取元素;推送元素;递减索引)直到到达元素 0。
IncArray2 不包含此类代码。调用者在调用 IncArray2 之前将数据的地址存储到 eax 寄存器中,而 IncArray2 只是使用该地址。
如果您出于任何原因不想使用“var”,您可以将数据的地址传递给您的方法。但是由于你不能在参数声明中使用语法'data: ^array of integer',你必须为你的数据声明一个类型。而且你必须在方法中的任何地方都使用 'data^' 而不是 'data'。
type
TData = array of integer;
PData = ^TData;
procedure IncArray(data: PData);
var i : integer;
begin
for i := Low(data^) to High(data^) do
data^[i] := data^[i] + 5;
end;
procedure TForm8.FormCreate(Sender: TObject);
var
data: TData;
begin
SetLength(data, 2);
data[0] := 37;
IncArray(@data);
Caption := IntToStr(data[0]);
end;
使用 Delphi 2007 测试。