我有两个具有相同字段的记录,其中一个具有一组过程。为什么两个记录的大小相同?
{$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.
答案 0 :(得分: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来检查参数列表的开头或末尾是否添加了参数,但我希望你明白这一点。
当然没有真正的语法,因为它是由编译器动态完成的,因此,例如,过程名称不会改变。我这样做是为了让我的答案易于理解。
答案 1 :(得分:0)
程序不占空间。编译器会正确地连接它们。它们的地址在运行时不需要在每个记录的内存中。如果你在内存中查看TData2的表示,你将找不到这些程序。