【发布时间】:2016-06-21 09:30:12
【问题描述】:
示例代码:
unit Main;
interface
uses
Winapi.Windows, System.SysUtils, Vcl.Forms;
type
TSomeRec = record
SomeData: Integer;
SomePtr: Pointer;
procedure Reset;
class operator Implicit(const SomeData: Integer): TSomeRec;
end;
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
private
FSomeRec: TSomeRec;
end;
var
MainForm: TMainForm;
GSomeRec: TSomeRec;
implementation
{$R *.dfm}
function SomeFunc(Value: Integer): TSomeRec;
begin
OutputDebugString(PWideChar(Result.SomeData.ToString + ' : ' + Integer(Result.SomePtr).ToString));
Result.SomeData := Value;
end;
{ TSomeRec }
procedure TSomeRec.Reset;
begin
SomeData := 5;
SomePtr := nil;
end;
class operator TSomeRec.Implicit(const SomeData: Integer): TSomeRec;
begin
OutputDebugString(PWideChar(Result.SomeData.ToString + ' : ' + Integer(Result.SomePtr).ToString));
Result.SomeData := SomeData;
end;
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
var
LSomeRec: TSomeRec;
begin
LSomeRec.Reset;
GSomeRec.Reset;
FSomeRec.Reset;
LSomeRec := 1;
GSomeRec := 1;
FSomeRec := 1;
LSomeRec.Reset;
GSomeRec.Reset;
FSomeRec.Reset;
LSomeRec := SomeFunc(1);
GSomeRec := SomeFunc(1);
FSomeRec := SomeFunc(1);
end;
end.
这段代码给出了这个调试输出:
Debug Output: 5 : 0 Process DPITest.exe (1764)
Debug Output: 172555996 : 1638080 Process DPITest.exe (1764)
Debug Output: 1 : 1638080 Process DPITest.exe (1764)
Debug Output: 5 : 0 Process DPITest.exe (1764)
Debug Output: 1 : 1638080 Process DPITest.exe (1764)
Debug Output: 1 : 1638080 Process DPITest.exe (1764)
似乎编译器为不同的变量创建了不同的代码:
- LSomeRec 它们作为 var 参数传递(如预期的那样)。
- 为 GSomeRec 和 FSomeRec 编译器创建临时变量,传递给她,然后为普通变量赋值。
这正常吗?如果正常,请给我规范(文档)的链接。
PS
一个小补充...
Here是这样写的:
对于静态数组,记录和设置结果,如果值占一 在 AL 中返回的字节;如果该值占用两个字节,则为 在 AX 中返回;如果该值占用四个字节,则返回 EAX。否则,结果将在附加的 var 参数中返回 在声明的参数之后传递给函数
但实际上,这条规则并不满足。如果它包含调试器输出将如下:
Debug Output: 5 : 0 Process DPITest.exe (1764)
Debug Output: 5 : 0 Process DPITest.exe (1764)
Debug Output: 5 : 0 Process DPITest.exe (1764)
Debug Output: 5 : 0 Process DPITest.exe (1764)
Debug Output: 5 : 0 Process DPITest.exe (1764)
Debug Output: 5 : 0 Process DPITest.exe (1764)
【问题讨论】:
-
我不认为这是重复的 - 正在初始化的返回值是答案的一部分,但我认为 OP 期望
implicit类运算符的行为与它不同。具体来说,他们似乎期望result将预先加载左侧变量的记录内容(即:运算符将为零碎的赋值/替换提供目标记录)。事实并非如此。 -
我没有把它读进去,我看不出作为骗子关闭有什么不好。我们被积极鼓励这样做。建立这些链接对每个人都有帮助。除了未初始化的返回值之外,我看不出还有什么其他的。
-
@Vasek 您的重置方法正在自找麻烦。改变值的值类型的方法确实容易引起混淆。更喜欢使用简单的常量赋值。
-
@DavidHeffernan 对我来说,这似乎是对运算符重载的基本误解。在这里,当进行像
GSomeRec := 1这样的赋值时,OP 似乎期望函数中的result将引用运算符左侧的变量(即:运算符重载提供了仅部分修改记录的机会分配给而不是要求操作员分配给或完全初始化新记录以进行分配)。幸运的是,这适用于局部变量(至少在这种情况下),但行为通常是未定义的。 -
只有两个函数返回一个未初始化的值。
标签: delphi