我需要澄清这个案子。
根据我的测试,结果变量定义为:
从第一行开始,Boolean=False、Integer=0、String=''、Object=nil 等。
但我从未见过这方面的官方参考。
这也是有道理的,因为这给出了暗示。
[DCC 警告] Unit1.pas(35):H2077 分配给“TForm1.Test”的值从未使用过
function TForm1.Test: Boolean;
begin
Result := False;
// Some arbitrary code here
Result := True;
end;
但是,如果我注释掉第一行并且最后一行之前的某处出现异常,会发生什么情况?结果=假吗?
如果 Result 未定义,这意味着我always必须通过定义 Result 来启动每个函数,以防稍后出现异常。这对我来说毫无意义。
正如所指出的Delphi 官方文档,结果是:
- CPU 寄存器 (AL / AX / EAX / RAX / EAX:EDX) 用于寄存器中包含的序数值和元素;
- FPU 寄存器(st(0) / XMM1);
- 作为最新参数传递的附加变量。
一般规则是默认情况下不定义结果值。你必须设置它。编译器将警告您任何丢失的结果集。
对于字符串、动态数组、方法指针或变量结果,
效果与函数结果被声明为相同
声明参数后面的附加 var 参数。其他
换句话说,调用者传递一个额外的 32 位指针,该指针指向
返回函数结果的变量。
准确地说,var
参数不仅适用于托管类型,而且仅适用于record
or object
结果在调用之前在堆栈上分配,因此具有相同的行为。
也就是说,例如,如果您的结果是string
,它将作为附加传递var
范围。因此它将默认包含调用之前的值。这将是''
首先,如果多次调用该函数,它将包含以前的值。
function GetString: string;
// is compiled as procedure GetString(var result: string);
begin
if result='' then
result := 'test' else
writeln('result=',result);
end;
function GetRaise: string;
// is compiled as procedure GetRaise(var result: string);
begin
result := 'toto';
raise Exception.Create('Problem');
end;
var s: string;
begin
// here s=''
s := GetString; // called as GetString(s);
// here s='test'
s := GetString; // called as GetString(s);
// will write 'result=test' on the console
try
s := GetRaise; // called as GetRaise(s);
finally
// here s='toto'
end;
end;
所以我的建议是:
- 修复所有有关未设置结果的编译器警告;
- 不要假设结果字符串被初始化为 '' (可能是第一次,但不是在第二次调用时) - 这是作为
var
参数,不作为out
范围;
- Any
exception
将被处理as usual,即运行的流程会跳转到下一个finally
or except
块 - 但如果你有一个结果作为var
参数,并且某些内容已经分配给result
,该值将被设置;
- 这并不是因为在大多数情况下,未设置的结果序数值(例如布尔值)为 0(因为在返回之前的 asm 代码中 EAX=0),所以下次会出现这种情况(我在客户端看到过随机问题)由于这种未设置的结果变量:它在大多数情况下都有效,然后有时代码会失败......);
- 您可以使用
exit()
在较新版本的 Delphi 上返回值的语法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)