我可以强制`const`通过引用传递(也就是缺少的`in`参数)

Joh*_*ica 10 delphi pass-by-reference

德尔福有:

var:通过引用传递; 参数是输入和输出.
out:通过引用传递; 参数仅输出.
const:通过......好吧,这取决于; 参数仅为输入.
in :通过引用传递; 参数仅为输入,不会更改 没有"在".

我不介意没有勺子,但我想念in; 考虑到以下代码,是否有更简洁的方法来做到这一点?

type TFastDiv = record 
strict private
  FBuffer: Int64;
  other fields
....

//Must be `var` because `const` would pass a Int64 by value
//                      |||
//                      VVV
function DivideFixedI32(var Buffer: Int64; x: integer): integer;
asm  
  mov  r9,rcx                   
  imul dword ptr[rcx]    // do stuff with the buffer
  ..
  mov     ecx, [r9+4]    // do other stuff with the rest of the buffer  
Run Code Online (Sandbox Code Playgroud)

{将代码更改为imul ecx;...;shr r9,32;mov ecx,r9d允许按值传递,但我们假设代码不得更改.}

class operator TFastDiv.IntDivide(x:integer; const buffer:TFastDiv):integer;
begin
  Result:= DivideFixedI32(Int64((@buffer.FBuffer)^), abs(x)); <<-- Ugly
  if (x < 0) then Result:= - Result;
end;
Run Code Online (Sandbox Code Playgroud)

DivideFixed永远不会改变缓冲区.例程的重点是buffer预先计算的值不会改变.

在类运算符中,我将缓冲区声明为const,因为记录不能更改.

现在的问题是:
如果我坚持声明buffer参数IntDivide作为const有编码的更清洁的方式还是我停留在pointer_to/points_to破解?

Chr*_*ton 13

较新的编译器版本(从XE3开始)支持[Ref]装饰器:

procedure Foo(const [Ref] Arg1: Integer; [Ref] const Arg2: Byte);
Run Code Online (Sandbox Code Playgroud)

文档中改编的示例,强调[Ref]可以在const关键字之前或之后进行.

  • +1非常好.你知道哪些编译器支持这个吗?桌面编译器会这样做吗? (3认同)

Joh*_*ica 6

如果你想确保传递引用,唯一的选择(pre Delphi XE3)就是传递一些东西.
即大于sizeof(指针)

type TFastDiv = record 
strict private
  FBuffer: Int64;   <<-- make sure this is the first member
  other fields
....

function DivideFixedI32(const Buffer: TFastDiv; x: integer): integer;
...
class operator TFastDiv.IntDivide(x:integer; const buffer:TFastDiv):integer;
begin
  Result:= DivideFixedI32(buffer, abs(x));
Run Code Online (Sandbox Code Playgroud)

这行在Delphi帮助文件中:

设置,记录和1,2或4个字节的静态数组作为8位,16位和32位值传递.较大的集合,记录和静态数组作为32位指针传递给该值.此规则的一个例外是记录总是直接在cdecl,stdcall和safecall约定下的堆栈上传递; 以这种方式传递的记录的大小向上舍入到最近的双字边界.

是误导性的,应改为/读作:

直到SizeOf(指针)的集合,记录和静态数组作为8位,16位和32位值(x64上的64位值)传递.大于SizeOf(指针)的集合,记录和静态数组作为指针传递给值.此规则的一个例外是记录总是直接在cdecl,stdcall和safecall约定下的堆栈上传递; 以这种方式传递的记录的大小向上舍入到最近的SizeOf(指针)边界.