2

我注意到不同的代码以与我不同的方式声明参数,我想知道这样做是否有特定的原因,或者是否是一种偏好。

假设我写了这个函数(只是一个不同参数的例子)

function DoSomething(AHeight, AWidth: Integer; R: TRect): Boolean
begin
  //
end;

如果这样声明,这有什么不同:

function DoSomething(var AHeight, AWidth: Integer; const R: TRect): Boolean
begin
  //
end;

我知道一个变量是可读/写的,而一个常量是只读的,但是以这种方式声明参数有什么不同呢?

对我来说,这两个函数都在寻找调用代码来提供高度、宽度和矩形,但是第二个函数使它看起来像是在声明新变量。

我有一种感觉,这将是一个直截了当的答案,我觉得问起来很傻,但我必须知道有什么区别,如果有的话?

4

3 回答 3

4

文档非常清楚地解释了这一点:

大多数参数要么是值参数(默认),要么是变量(var)参数。值参数通过值传递,而可变参数通过引用传递。要了解这意味着什么,请考虑以下函数:

function DoubleByValue(X: Integer): Integer;   // X is a value parameter
begin
  X := X * 2;
  Result := X;
end;

function DoubleByRef(var X: Integer): Integer;  // X is a variable parameter
begin
  X := X * 2;
  Result := X;
end;

这些函数返回相同的结果,但只有第二个 - DoubleByRef 可以更改传递给它的变量的值。假设我们这样调用函数:

var
  I, J, V, W: Integer;
begin
  I := 4;
  V := 4;
  J := DoubleByValue(I);   // J = 8, I = 4
  W := DoubleByRef(V);     // W = 8, V = 8
end;

执行此代码后,传递给 DoubleByValue 的变量 I 具有我们最初分配给它的相同值。但是传递给 DoubleByRef 的变量 V 具有不同的值。

值参数的作用就像一个局部变量,它被初始化为过程或函数调用中传递的值。如果您将变量作为值参数传递,则过程或函数会创建它的副本;对副本所做的更改对原始变量没有影响,并且在程序执行返回给调用者时丢失。

另一方面,变量参数的作用类似于指针而不是副本。在程序执行返回调用者并且参数名称本身超出范围后,对函数或过程主体内的参数所做的更改仍然存在。

即使在两个或多个 var 参数中传递相同的变量,也不会制作副本。这在以下示例中进行了说明:

procedure AddOne(var X, Y: Integer);
begin
  X := X + 1;
  Y := Y + 1;
end;

var I: Integer;
begin
  I := 1;
  AddOne(I, I);
end;

这段代码执行后,I 的值为 3。


我建议您将Delphi 语言指南的链接添加到浏览器的书签中。

于 2012-07-25T09:31:31.530 回答
2

这里有一个很好的讨论,但基本上,没有var,参数是按值传递的,而使用var,参数是按引用传递的。

当通过值传递参数时,会生成参数的副本,并将该副本提供给函数。对副本的任何更改都不会传播到单独的原始文件。

当通过引用传递参数时,该函数将获得对原始的引用,因此即使在进行调用之后,对副本的任何更改都将可见。

于 2012-07-25T09:32:11.717 回答
1

参数可以是 var、const、out 和 'none'

通常,函数可以更改参数,但不会更改调用参数。

var
  x,y : Integer;
procedure Text(a: Integer);
begin
  x := a;
  a := 1;
end;
begin
  x := 10;
  y := 20;
  Test(y);
  // x = 20; y = 20;
end.

使用 var 参数,更改会影响调用参数。

var
  x,y : Integer;
procedure Text(var a: Integer);
begin
  x := a;
  a := 1;
end;
begin
  x := 10;
  y := 20;
  Test(y);
  // x = 20; y = 1;
end.

一个 const 参数,不能更改。

var
  x,y : Integer;
procedure Text(const a: Integer);
begin
  x := a;
  a := 1; // ERROR!
end;
begin
  x := 10;
  y := 20;
  Test(y);
  // Does not compile
end.

仅写入输出参数。

var
  x,y : Integer;
procedure Text(out a: Integer);
begin
  x := a;
  a := 1;
end;
begin
  x := 10;
  y := 20;
  Test(y);
  // x = undefine y = 1;
end.
于 2012-07-25T09:37:06.307 回答