编译器提示:"内联函数'......'尚未扩展......"

Hol*_*rwa 15 delphi winapi

在一个单元中我使用该函数DeleteFile,编译器输出一个提示:

"H2443内联函数'DeleteFile'尚未展开,因为在USES列表中未指定单位'Windows'"

Uses那里SysUtils,它定义DeleteFile(虽然内部调用Windows.DeleteFile).

这个提示意味着什么?如果我Windows加入该Uses条款,它已经消失了,但我想了解困扰编译器的是什么.

Dav*_*man 24

这是一个内联限制.

请参阅Hallvard Vassbotn关于Inlined Routines的文章.

从该网站提取:

其余的内联限制对于两个平台都是通用的,而最重要的是

  • 没有跨包边界内联
  • 内联例程无法访问实现部分标识符
  • 呼叫站点必须能够访问内联例程中使用的所有标识符

注意最后一点意味着除非调用站点单元使用例程所需的单位,否则不能内联例程.发生这种情况时,编译器会发出这样的提示

 [Pascal Hint] InlinedRoutinesU.pas(14): H2443 Inline function 
   'InlineMe' has not been expanded because unit 'RequiredUnit' 
    is not specified in USES list 
Run Code Online (Sandbox Code Playgroud)

要解决此问题,请将缺少的单元名称添加到调用站点的uses子句中.


Too*_*the 12

内联函数可以内联扩展.例如:

function AddPlus(const A,B: Integer): Integer; inline;
begin
  Result := A + B + 1;
end;

var
  x,y,z : Integer;
begin
  y := 22;
  z := 11;
  x := AddPlus(y, z);
end.
Run Code Online (Sandbox Code Playgroud)

被重写为:

var
  x,y,z : Integer;
begin
  y := 22;
  z := 11;
  x := y+z+1;
end.
Run Code Online (Sandbox Code Playgroud)

这消除了函数调用的开销.

但是为了用函数体替换调用,编译器需要更多的信息,因此关于单元的抱怨.

请注意,并非所有内联函数都已转换.有些被视为普通函数(由编译器决定).此外,仅在非常严格的性能瓶颈时才需要内联.


Ian*_*oyd 8

我也对这个提示感到困惑.然后我意识到问题是什么.你的代码:

uses
   SysUtils;

procedure TForm1.DoStuff;
begin
   SysUtils.DeleteFile('foo');
end;
Run Code Online (Sandbox Code Playgroud)

实际上被替换为:

uses
   SysUtils;

procedure TForm1.DoStuff;
var
  Flags, LastError: Cardinal;
begin
  Result := Winapi.Windows.DeleteFile(PChar(FileName));

  if not Result then
  begin
    LastError := GetLastError;
    Flags := GetFileAttributes(PChar(FileName));

    if (Flags <> INVALID_FILE_ATTRIBUTES) and (faSymLink and Flags <> 0) and
      (faDirectory and Flags <> 0) then
    begin
      Result := RemoveDirectory(PChar(FileName));
      Exit;
    end;

    SetLastError(LastError);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

如果您注意到,您的"新"代码取决于WinApi.Windows单位:

Result := Winapi.Windows.DeleteFile(PChar(FileName));
Run Code Online (Sandbox Code Playgroud)

您未在uses条款中包含的内容.

如果手动内联代码(复制和粘贴),代码将无法编译,直到您添加Windows到您的代码uses.

相反,编译器不会这样做,inline因为:

内联函数'DeleteFile'尚未展开,因为在USES列表中未指定单位'Windows'

  • "实际上正在被替换为" - 在您展示它时并不完全正确,因为内联过程必须进行调整以处理函数调用的参数和结果值,该函数调用在应用内联后不再是函数调用.但是你的答案是正确的 - "SysUtils.DeleteFile()"里面的代码被带入调用代码,它需要引用`Windows`单元来满足API调用,否则内联会失败编译. (3认同)