Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 为什么记录构造函数在内联函数中表现不好?_Delphi_Record_Compiler Bug - Fatal编程技术网

Delphi 为什么记录构造函数在内联函数中表现不好?

Delphi 为什么记录构造函数在内联函数中表现不好?,delphi,record,compiler-bug,Delphi,Record,Compiler Bug,在下面的代码中,记录构造函数执行了一些奇怪的操作。 它在所有情况下都正常工作,但在下面标记的行中除外: program Project9; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Generics.Collections; type TIntegerPair = TPair<Integer, Integer>; type TMiniStack<T> = record

在下面的代码中,记录构造函数执行了一些奇怪的操作。
它在所有情况下都正常工作,但在下面标记的行中除外:

program Project9;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  System.Generics.Collections;

type
  TIntegerPair = TPair<Integer, Integer>;

type
  TMiniStack<T> = record
  public
    Items: array[0..10] of T;
    SP: integer;
    procedure Init;
    procedure PushInline(const Item: T); inline;
    procedure PushNormal(const Item: T);
  end;

procedure TMiniStack<T>.Init;
begin
  FillChar(Items, SizeOf(Items), #0);
  SP:= 0;
end;

procedure TMiniStack<T>.PushInline(const Item: T);
begin
  Items[SP]:= Item;
  Inc(SP);
end;

procedure TMiniStack<T>.PushNormal(const Item: T);
begin
  Items[SP]:= Item;
  Inc(SP);
end;


procedure RecordConstructorFail;
var
  List1: TMiniStack<TIntegerPair>;
  List2: array[0..2] of TIntegerPair;
  Pair: TIntegerPair;
  a: string;
begin
  Writeln('start test...');
  FillChar(List1, SizeOf(List1), #0);
  List1.Init;
  List1.PushInline(TIntegerPair.Create(1, 1));
  List1.PushInline(Pair.Create(2, 2));   <<--- Failure
  List2[0]:= TIntegerPair.Create(1, 1);
  List2[1]:= Pair.Create(2, 2);
  if (List1.Items[0].Key <> 1) or (List1.Items[1].Key <> 2) then Writeln('something is wrong with List1-Inline');
  if (List2[0].Key <> 1) or (List2[1].Key <> 2) then Writeln('something is wrong with List1');
  List1.Init;
  List1.PushNormal(TIntegerPair.Create(1, 1));
  List1.PushNormal(Pair.Create(2, 2));
  if (List1.Items[0].Key <> 1) or (List1.Items[1].Key <> 2) then Writeln('something is wrong with List1-Normal');
  Writeln('Done');
  Readln(a);
  Writeln(a);
end;

begin
  RecordConstructorFail;
end.
程序项目9;
{$APPTYPE控制台}
{$R*.res}
使用
System.SysUtils,
系统、泛型、集合;
类型
TIntegerPair=TPair;
类型
TMiniStack=记录
公众的
项目:T的数组[0..10];
SP:整数;
程序初始化;
程序PushInline(常数项:T);内联;
程序正常(常数项:T);
结束;
程序TMiniStack.Init;
开始
FillChar(项目),SizeOf(项目),#0;
SP:=0;
结束;
程序TMiniStack.PushInline(常数项:T);
开始
项目[SP]:=项目;
公司(SP),;
结束;
程序TMiniStack.PushNormal(常数项:T);
开始
项目[SP]:=项目;
公司(SP),;
结束;
程序记录:施工失败;
变量
列表1:TMiniStack;
列表2:TIntegerPair的数组[0..2];
配对:TIntegerPair;
a:弦;
开始
Writeln('启动测试…');
FillChar(列表1,SizeOf(列表1),#0);
列表1.Init;
List1.PushInline(TIntegerPair.Create(1,1));

List1.PushInline(Pair.Create(2,2)) 在我看来,无论是内联的还是非内联的,作为实例上的构造函数调用的表达式都不会计算为值。因此不能作为参数传递。想到

Pair.Create(...)
好像这是一个程序。它没有任何价值

在我看来,编译器应该拒绝代码,而没有拒绝的事实就是错误

在我看来,当你不内联代码的时候,代码看起来是有效的,这是偶然的


不过这都是猜测。记录构造函数没有正确记录。用于构造函数的是类,尚未更新以覆盖记录。类的文档说明实例表单是一个引用实例的表达式

当使用对象引用(而不是类引用)调用构造函数时,它不会创建对象。相反,构造函数对指定的对象进行操作,只执行构造函数实现中的语句,然后返回对该对象的引用

但这对于记录来说没有多大意义,因为存在值类型而不是引用类型


我最好的猜测是解析器认为这个表达式与实例的类型相同,因为对于类的构造函数来说就是这样。但是codegen实际上并没有产生一个值

TIntegerPair.Create(1,1)
是正确的语法。然而,记录建设者是令人憎恶的,Emba疯狂地把他们推到我们身上。应该使用类静态函数。这样就不会有与类的构造函数混淆的危险。“失败”是什么意思?它不能编译吗?它是否引发了一个例外?它是否做了一些超出您预期的事情?@DavidHeffernan,我完全同意,记录构造函数甚至不能内联。我的建议是忽略它们。但是是的,它看起来确实像一个编译器错误。也就是说,我不确定对变量调用记录构造函数意味着什么。DavidM,因为当你阅读它们时,它们看起来就像一个类的构造函数,所以你假设你需要调用
Free
。更重要的是,它们不构造,而是初始化。记录总是以其他方式创建的。通常自动作为局部变量或复合结构的成员,或通过调用heap alloc。但决不能通过记录构造函数。因此,调用构造函数是自相矛盾的,构造是它不做的一件事。实际上,引用的文本对记录也是有意义的。当使用记录类型前缀调用时,记录构造函数充当类函数并返回值;当使用记录实例前缀调用记录构造函数时,记录构造函数充当实例过程,不返回任何内容。@用户,除非文本显示,然后返回对对象的引用
Pair.Create(...)