当前位置:  开发笔记 > 开发工具 > 正文

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

如何解决《编译器提示:"内联函数''尚未扩展"》经验,为你挑选了3个好方法。

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

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

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

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



1> Davy Landman..:

这是一个内联限制.

请参阅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 

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



2> Toon Krijthe..:

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

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.

被重写为:

var
  x,y,z : Integer;
begin
  y := 22;
  z := 11;
  x := y+z+1;
end.

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

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

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



3> Ian Boyd..:

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

uses
   SysUtils;

procedure TForm1.DoStuff;
begin
   SysUtils.DeleteFile('foo');
end;

实际上被替换为:

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;

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

Result := Winapi.Windows.DeleteFile(PChar(FileName));

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

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

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

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


"实际上正在被替换为" - 在您展示它时并不完全正确,因为内联过程必须进行调整以处理函数调用的参数和结果值,该函数调用在应用内联后不再是函数调用.但是你的答案是正确的 - "SysUtils.DeleteFile()"里面的代码被带入调用代码,它需要引用`Windows`单元来满足API调用,否则内联会失败编译.
推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有