我怎么知道内联函数是否实际被替换在它被调用的地方?

Abh*_*eet 37 c++ inline

我知道内联函数要么被调用,要么被称为普通函数.

但是,我如何知道内联函数是否实际被替换在它被调用的地方,因为将内联函数作为内联处理的决定是在编译时?

Alo*_*ave 59

在运行时以编程方式,你不能.
事情的真相是: 你不需要知道

编译器可以选择inline未标记的inline函数或忽略明确标记的函数inline,这完全是编译器的愿望(读智慧)并且您应该信任编译器明智地完成其工作.大多数主流编译器都能很好地完成它们的工作.

如果您的问题纯粹来自学术观点,那么有几种选择:


分析生成的汇编代码:

您可以检查汇编代码以检查函数代码是否在调用时内联.

如何生成汇编代码?

对于gcc:编译时
使用-S开关.
例如:

g++ -S FileName.cpp
Run Code Online (Sandbox Code Playgroud)

生成的汇编代码创建为文件FileName.s.

对于MSVC:从命令行
使用/ FA Switch.

在生成的汇编代码中查找是否存在call特定函数的汇编指令.


使用编译器特定的警告和诊断:

如果某些编译器未能遵守内联函数请求,则会发出警告.
例如,在gcc中,-Winline如果编译器没有内联声明为内联的函数,则命令选项将发出警告.

查看GCC文档以获取更多详细信息:

-Winline

如果无法内联声明为内联的函数,则发出警告.即使使用此选项,编译器也不会警告系统头中声明的内联函数失败.

编译器使用各种启发式方法来确定是否内联函数.例如,编译器会考虑内联函数的大小以及当前函数中已经完成的内联量.因此,源程序中看似微不足道的变化可能导致产生的警告-Winline出现或消失.

  • “你不需要知道”我再补充一下,废话。不要告诉我们我们做了什么以及不需要知道什么,您很可能经常会错。就我而言,它适用于极其快速的代码,而且我确实需要知道它将做什么。 (4认同)
  • “您不需要知道”不一定。如果您需要一个包装汇编代码的辅助函数,则非常重要。 (2认同)
  • 你说的“你不需要知道”是不对的。在我的代码中,我使用了堆栈溢出保护,所以当一个函数被内联时,检查代码是一个过多的开销。所以我想知道... (2认同)

Luc*_*ore 10

检查生成的代码.如果函数被展开,你将看到它的主体,而不是call类似的指令.

  • 与“call”“类似指令”的示例是什么?抱歉,我对装配不太了解。 (4认同)

ks1*_*322 7

您可以使用工具列出来自目标文件的符号,例如nm在Linux上.如果函数是内联的,它将不会在nm输出中列出- 它成为其他函数的一部分.此外,您将无法在调试器中按名称将断点放在此函数上.

  • @Als:好的,如果`nm`输出中没有该函数,这意味着它的所有实例都被内联了.它仍提供有关内联的一些信息. (6认同)
  • 在一个调用实例中可能内联相同的函数,而在另一个调用实例中可能没有内联,它完全取决于编译器.因此使用`nm`不是确定函数调用是否确实内联的可靠方法. (3认同)

Vla*_*nko 7

如果您需要确保该函数是内联的并且可以在 MS VC++ 中使用专有扩展,请查看__forceinlinedeclarator。编译器将内联函数,或者如果它属于记录的特殊情况列表,您将收到警告 - 因此您将知道内联状态。

不以任何方式认可它。

  • 是的,`__forceinline` 会删除编译器的成本/收益计算,并在可能的情况下内联函数。重要的是要注意它*仅*禁用成本/收益计算,但不能100%保证它被内联。 (3认同)

Per*_*-lk 5

使用gdb,如果你不能调用一个函数,它可能的含义之一就是该函数是内联的。翻转推理,如果您可以在 gdb 中调用函数,则意味着该函数未标记为内联。