"array of double" 和 TDoubleDynArray 的区别是什么?

4

System.Types单元声明了一个数组类型:

TDoubleDynArray  = array of Double;

如果我将一个方法声明为:
procedure func (x : TDoubleDynArray)

我注意到参数x的行为类似于var参数,也就是说,我可以在方法内部更改x,并且我会看到方法外部反映出这些变化。
然而,当我使用
procedure func (x : array of double)

正如预期的那样,对x的任何更改都会保留在func中。虽然TDoubleDynArray似乎被声明为double的数组,但它的行为与我自己的double的数组不同。这是什么原因呢?
更新:我注意到如果我声明自己的类型TMyArray = array of double,那么我将得到与TDynamicDynArray相同的行为。这是否与基本数组类型之间的差异有关?
测试代码如下
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses System.Types;

var
   x : TDoubleDynArray;
   y : array of double;

procedure func1 (x : TDoubleDynArray);
begin
  x[0] := -999.123;
end;

procedure func2 (y : array of double);
begin
  y[0] := -999.123;
end;

begin
    setLength (x, 10);
    func1 (x);
    writeln ('TDoubleDynArray: ', x[0]);

    setLength (y, 10);
    y[0] := 0;
    func2 (y);
    writeln ('array of double: ', y[0]);

    Readln;
end.
1个回答

7
procedure func1 (x : TDoubleDynArray);

函数参数是一个动态数组。那是一个引用类型。这意味着函数参数x是对数组的引用。由此带来的结果是,在func1内部更改数组元素会更改调用者的数组。

procedure func2 (y : array of double);

该函数参数是一个开放数组参数。尽管它重载了array of语法,但它与动态数组截然不同。由于这个开放数组是按值传递的,因此数组的副本被传递到函数中,所以函数所做的修改对调用者不可见。
值得指出的是,因为您按值传递了y,所以会传递数组的副本。这是低效的,特别是对于较大的数组来说更是如此。一般而言,应避免使用按值开放数组。使用varconst开放数组参数。相同的建议也适用于其他大型类型,如固定长度数组和记录。
开放数组参数是混淆的无穷源泉。我建议您阅读我链接到的文档,以及Rudy关于此主题的文章:Open array parameters and array of const

你的回答中还有一个问题。如果我声明了一个类型TMyArray = array of double,并使用该类型来声明参数,那么该参数会变成动态数组吗? - rhody
正确。TMyArray 是一个动态数组。 - David Heffernan
@rhody: 在参数声明中直接使用X的数组将创建一个“开放数组”。而任何其他使用X的数组的情况都会创建一个动态数组。 - Remy Lebeau
不能只是在函数参数中添加“const”来避免创建副本吗? - Hans
@Hans 是的,正如答案中所述。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接