8

我有两条具有相同字段的记录,其中一条有一组程序。为什么两条记录的大小相同?

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TData = record
    Age : Byte;
    Id  : Integer;
  end;

  TData2 = record
    Age : Byte;
    Id  : Integer;
    procedure foo1;
    procedure foo2;
    procedure foo3;
  end;

procedure TData2.foo1;
begin

end;

procedure TData2.foo2;
begin

end;

procedure TData2.foo3;
begin

end;

begin
  try
    Writeln('SizeOf(TData) = '+ IntToStr(SizeOf(TData)));
    Writeln('SizeOf(TData2) = '+ IntToStr(SizeOf(TData2)));
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.
4

2 回答 2

10

那是因为记录本身只携带构成记录的数据,没有过程或功能。过程和函数是一种语法糖,以避免将记录本身作为参数传递:编译器为您自动添加的self变量。

您在记录中声明的每个方法都有记录本身的另一个参数,例如:

  TData2 = record
    Age : Byte;
    Id  : Integer;
    procedure Foo1;
    procedure Foo2(SomeParam: Integer);
  end;

更改为等效于:

  PData2 = ^TData2;

  TData2 = record
    Age : Byte;
    Id  : Integer;
  end;

  procedure TData2_Foo1(Self: PData2);
  procedure TData2_Foo2(Self: PData2; SomeParam: Integer);

结束您拨打的每个电话也会更改,例如:

var
  Data: TData2;
begin
  Data.Foo1;
  Data.Foo2(1);
end;

更改为等效于:

var
  Data: TData2;
begin
  TData2_Foo1(@Data);
  TData2_Foo1(@Data, 1);
end;

我手头没有 Delphi 来检查参数是添加在参数列表的开头还是末尾,但我希望你能明白。

当然,这并没有真正的语法,因为它是由编译器动态完成,因此,例如,过程名称不会更改。我这样做是为了让我的答案易于理解。

于 2013-01-16T03:04:58.703 回答
0

程序不占用空间。编译器会正确连接它们。对于每条记录,它们的地址在运行时不需要在内存中。如果您查看 TData2 在内存中的表示,您将找不到这些过程。

于 2013-01-16T03:03:37.240 回答