0

我知道在类成员函数中添加 inline 关键字后,如果“函数不复杂”或者函数体中有“很多语句”,编译器会决定内联。

  1. 什么被认为是“很多陈述”?

  2. 如果函数的地址被隐式或显式获取,编译器也无法执行内联。谁能解释这一点?

  3. 而且因为 inline 只是一个建议,我如何测试哪些函数没有被内联?

4

4 回答 4

4
  1. 编译器是否生成内联代码取决于编译器。大多数现代编译器将生成几乎所有非递归内联的东西。

  2. 这完全是错误的。获取地址时,编译器必须为该地址生成一个行外副本,但这并不妨碍它在调用函数时内联。

  3. 你没有。

于 2013-08-16T16:00:02.920 回答
4
  1. 这完全取决于编译器;这可能取决于优化设置、目标架构的特性(例如,函数调用的成本与由于代码大小增加而导致的缓存未命中的潜在成本)以及函数与其余代码的集成程度在特定的呼叫站点。

  2. 如果一个函数总是内联的,它本身就不再作为一个函数存在,因为它的指令直接放在调用站点上,其余的调用者代码;出于这个原因,这样的函数不再有地址,因为它与调用者混合在一起。但是,当您请求函数地址时,通常会发生的情况是编译器会在它最喜欢的地方内联函数,但仍将其作为“常规函数”发出,通过函数指针使用其地址。

  3. 您可以反汇编生成的可执行文件,或者要求编译器发出程序集而不是构建完成的可执行文件(gcc可以-S选择)并手动检查它。尽管如此,请注意检查优化的二进制文件并非易事——因为内联代码与调用者代码混合在一起,可能很难准确地找出内联函数的去向,同时您也可能会在非内联的副本中找到通过函数指针使用的函数(如上所述)。

于 2013-08-16T16:03:05.440 回答
2
  1. 完全由编译器设计者决定使用什么启发式方法来决定是否内联函数调用。希望它基于生成的代码大小而不是“语句”的数量,这是一个完全没有意义的指标。希望它还包括对性能增益的估计,以权衡代码大小的任何增加。

  2. 如果地址被占用,那么必须有一个函数的非内联实例,以便有一些东西可以获取地址。但是,如果编译器决定应该内联,这不会阻止对函数的任何调用被内联。

  3. 你可以反汇编生成的代码,看看是否有函数调用。如果调用函数很大,或者它本身内联在另一个函数中,这可能会很棘手。大多数编译器都有一种(非标准的)强制内联方式;但只有在您确定自己比编译器更了解并且有测量结果来证明这一点时才使用它。

于 2013-08-16T16:06:24.760 回答
1

至于您关于编译器何时可能内联的问题,请查看此线程:

编译器是否决定何时内联我的函数(在 C++ 中)?

于 2013-08-16T15:55:40.437 回答