代码之家  ›  专栏  ›  技术社区  ›  Holgerwa

编译器提示:“内联函数'…'尚未展开…”

  •  14
  • Holgerwa  · 技术社区  · 17 年前

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

    “h2443内联函数'deletefile'尚未展开,因为在使用列表中未指定单元'windows'”

    Uses SysUtils 定义 删除文件 (尽管内部呼叫 Windows.DeleteFile )

    这个暗示是什么意思?如果我放 Windows 进入 使用 子句,它已经不存在了,但我想知道是什么困扰编译器。

    4 回复  |  直到 11 年前
        1
  •  24
  •   Davy Landman    17 年前

    这是一个内在的限制。

    参见哈尔瓦德·瓦斯博顿关于 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
  •  10
  •   Toon Krijthe    15 年前

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

    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
  •  6
  •   Ian Boyd    11 年前

    我也对这个暗示感到困惑。然后我意识到问题所在。您的代码:

    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 对你 使用 .

    相反,编译器不会执行 inline 因为:

    内联函数“deletefile”尚未展开,因为“uses”列表中未指定单元“windows”。

        4
  •  0
  •   RobS    17 年前

    内联函数由编译器就地扩展,避免了函数调用的开销。例如,对于平方,sqr(x)被编译为x*x,而不是调用一个乘以x并返回结果的函数。