Delphi如何使用Pointer(无类型)参数解决重载函数?

Ari*_*The 6 arrays delphi pointers overloading overload-resolution

以下是一些重载函数.试着猜出那些被调用的功能.

program Project2;
    {$APPTYPE CONSOLE}

uses
  Types, SysUtils;

procedure Some(const Buf); overload;
  begin
    Writeln('const-typeless')
  end;

//procedure Some(var Buf); overload;
//  begin
//    Writeln('var-typeless')
//  end;

//procedure Some(Buf :TByteDynArray); overload;
//  begin
//    Writeln('Byte dynamic array');
//  end;

procedure Some(Buf :array of Byte); overload;
  begin
    Writeln('Byte open array');
  end;

procedure Some(Buf :TArray<Byte>); overload;
  begin
    Writeln('TBytes AKA byte generic array');
  end;

//procedure Some(Buf :TBytes); overload;
//  begin
//    Writeln('TBytes AKA byte generic array');
//  end;

var p: pointer;

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
    WriteLn ('Calling overloaded procedure with Pointer parameter:');

    Write('  * nil: '); p := nil; Some(p);
    Write('  * garbage: '); p := Pointer(1); Some(p);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

  ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)

事实上,第二个被叫,并在第二次通话时抛出AV.给定旧的VCL模式使用PointerInteger可互换(例如TListTStrings.ObjectsTWinControl.Tag)可能导致相当规则的代码上的意外AV.

{$ T +}不会改变行为,因此并不是Delphi认为^Byte的那样Pointer.

然而,声明p: PInteger;修复它.此外,open-array变量不会被指针调用,并且与generic-array变量的处理/名称不同.动态数组的名称与通用数组不同,因此两者都可以使用,但在调用站点,如果两个都没有注释,则会发生模糊的重载错误.但是,如果要编译禁用通用数组并且取消注释dinamic数组 - 会发生同样奇怪的行为.

为什么编译器在参数为a时解析为动态/通用数组Pointer,并在参数为PInteger?时解析为常量无类型?

PS.开设QC 109019

Dav*_*nan 5

没有这方面的文档,所以我们能做的最好的事情就是编译并尝试猜测其行为背后的原因.

现在,具有无类型参数的过程可以传递任何参数,而不管其类型如何.因此,任何理智的重载解析方案都必须考虑无类型参数last,只有当它已经耗尽所有其他可能的候选者时.否则总会被选中.

因此,可以解释行为.

  • 当您的参数是类型时Pointer,该赋值与动态数组兼容.这意味着可以选择动态数组重载.
  • 当您的参数是任何其他指针类型时,它不与动态数组分配兼容.因此,重载决策回落到最终可能的候选者,即无类型参数.

最终,这种行为归结为编译器认为Pointer与任何动态数组兼容的赋值.这个陈述是事实很容易通过实验确认,但是,我找不到它的文档.

  • 下面是暗示这个问题的片段,但是用了非常模糊和不明确的词语: *动态数组变量是隐式指针,并且由用于长字符串的相同引用计数技术进行管理。要释放动态数组,请将 nil 分配给引用该数组的变量或将该变量传递给 Finalize;如果没有其他引用,这些方法都会处理该数组。当动态数组的引用计数降至零时,动态数组会自动释放。长度为 0 的动态数组的值为 nil.* (2认同)
  • *不要将解引用运算符 (^) 应用于动态数组变量或将其传递给 New 或 Dispose 过程。* http://docwiki.embarcadero.com/RADStudio/en/Structured_Types#Dynamic_Arrays 它不讨论 Poitners明确地,但没有引用并且声明了“隐式指针”。看起来像是经典的“这不是错误,这是功能”的态度。 (2认同)