文章

Delphi的函数返回值和函数参数引用说明

在 Object Pascal 里面,我们可以把 if 判断式成立时要执行的两个指令,用一
个 Exit 指令来取代,Exit 指令可以直接把要当做回传值的数值当成参数,就
像 C 语言里面的 return 指令一样。所以我们可以把上面的程序代码写的更精
简,也就可以省下一个 begin-end 的区块了:

function CharInString2 (S: string; Ch: Char): Boolean;
var
 I: Integer;
begin
 Result := False;
 for I := Low (S) to High (S) do
 if (S[I]) = Ch then
 Exit (True);
end;

在 Object Pascal 里面,Exit 是一个函式,所以回传值必须括在小括号里面,
C 语言的 return 是一个编译程序的关键词,所以 return 不用把回传值用小括
号当成参数括起

引用参数(Reference Parameters)
在 Object Pascal 里面,程序和函式传递参数时,包含了传值和传址两种方式。
预设的参数传递是以传值的方式进行的:作为参数传递进入子程序的数值或
变量,会被复制一份放在堆栈里,子程序将会使用复制出来的这份数值在整
个子程序里面使用,所以即使在子程序里面修改了这个复制的数值,呼叫前
的参数变量或数值,也都不会有任何改变。(就像我们稍早在函式的参数与
回传值章节所介绍的那样)

透过传址的方式来传递参数,则表示不会复制数据到子程序里面去,而是会
把当做参数的变量内存地址传进子程序,让子程序直接使用该参数的内存地
址,因此子程序只要对这个参数做了任何修改,就会同时修改到呼叫子程序
时所传递的变量内容。要使用引用参数,在宣告参数的时候,只要在参数前
面加个 var 关键词即可。

这个技术在大多数的程序语言里面都有提供,也因为不用复制变量内容,通
常程序执行的速度会快上一些。这个作法在 C 语言里面就没有提供(我们可
以使用指标来达成一样的效果),但在 C++跟其他使用 C 语言语法的语言里
面则也有提供此功能,我们可以透过&这个符号(意味着传址)来达成传址的
目的。以下是使用 var 关键词提供引用参数的写法:

procedure DoubleTheValue (var Value: Integer);
begin
 Value := Value * 2;
end;

在这个案例中,参数既扮演了传递数值让子程序进行计算的角色,也同时把
计算完成的结果带回给呼叫它的程序,也就是回传值的角色。如果我们这么
写:

var
X: Integer;
begin
 X := 10;
 DoubleTheValue (X);
 Show (X.ToString);

变量 X 的内容会在呼叫了 DoubleTheValue 函式之后变成 20,因为这个函式
使用的是引用参数,会直接使用变量 X 的内存地址,直接影响变量 X 的内
容。

跟传统的传值参数规则比较一下,引用参数所传递的不只是参数里面的数
值,而是把整个参数传过去,所以引用参数不能接受把常数、表达式、函式
的回传值,或是类别的属性当成引用参数传递。另一个规则则是不能传递不
同型别的变量(必须要先经过转型)。变量的型别跟参数的型别必须完全一
致,不然编译程序又要抱怨有错了:

[dcc32 Error] E2033 Types of actual and formal var parameters must be identical
var
C: Cardinal;
begin
 C := 10;
 DoubleTheValue (C);

以引用参数来传递有序型别或记录型别(我们会在下一章介绍)的参数是很
有用的。这些型别通常被称为值类型,因为它们的语法含义原本就是传值或
者指派数值的作法。
Object Pascal的字符串跟对象则是完全不同的规则,我们稍后会更深入讨论。
对象变量原本就是内存地址,所以当我们把对象当做参数传递的时候,本来
就会变动到该对象的原始内容。这些型别比较特殊,通常被称为『参考型别』。

除了标准的引用参数型别之外,Object Pascal 还提供另外一种很特别的参数
关键词: out。out 参数不用具备初始值,它只用来把数据回传给呼叫者,除
了不用提供初始值以外,其他的规则,out 跟 var 几乎都一样。

out 参数是为了兼容 Windows 的 COM 模式而被创造出来的。除了在
Windows COM 模式与对象的程序代码,在其他程序中几乎没有被使用过,
通常 out 参数会被认为在效能上会比 var 参数来的好

原文来自:Delphi的函数返回值和函数参数引用说明,尊重自己,尊重每一个人;转发请注明来源!
0 0

发表评论