假设我有一个名为TSomeRec
的记录类型:
type
TSomeRec = record
// ...
end;
...以及一个带有const TSomeRec
参数的过程:
procedure SomeProc(const someRec: TSomeRec);
begin
// ...
end;
调用SomeProc
时,const someRec
参数是作为值还是作为引用传递给堆栈的?
我问的原因是,在我正在处理的代码中,有问题的记录类型包含一个大规模的静态数组,因此是巨大的。 (不,我无法改变它。)我很担心将这么大的记录放在堆栈上,我认为const
可能有所帮助。这个代码溢出堆栈时遇到了问题,当发生这种情况时,我只会遇到神秘的访问冲突而不是任何堆栈溢出错误。
答案 0 :(得分:9)
这取决于。这实际上是在在线帮助中描述的,但现在就是这样。
在32位Windows可执行文件中(即使用WIN32定义编译的代码),如果记录不大于32位寄存器,则按原样推送到堆栈,即按值传递 。如果记录大于寄存器,则传递指向记录的指针,即通过引用传递。这是默认的register
调用约定。对于其他平台或调用约定可能有所不同,但上述情况很可能是一般情况。
常量参数可以通过值或引用传递给函数,具体取决于所使用的特定编译器。要强制编译器通过引用传递常量参数,可以将[Ref]装饰器与const关键字一起使用。
But see the Delphi Language Guide too。它描述了如何传递所有类型的参数,例如
将1,2或4个字节的集合,记录和静态数组作为8位,16位和32位值传递。较大的集合,记录和静态数组作为32位指针传递给该值。此规则的一个例外是记录总是直接在cdecl,stdcall和safecall约定下的堆栈上传递;以这种方式传递的记录的大小向上舍入到最近的双字边界。
但是,对于较新的编译器而言已经发生了变化。
但可以肯定的是,您可以随时查阅CPU视图。在那里你可以看到会发生什么。