【发布时间】:2013-08-16 15:48:29
【问题描述】:
我知道在类成员函数中添加 inline 关键字后,如果“函数不复杂”或者函数体中有“很多语句”,编译器会决定内联。
什么被认为是“很多陈述”?
如果函数的地址被隐式或显式获取,编译器也无法执行内联。谁能解释一下这一点?
因为内联只是一个建议,我该如何测试哪些函数没有内联?
【问题讨论】:
我知道在类成员函数中添加 inline 关键字后,如果“函数不复杂”或者函数体中有“很多语句”,编译器会决定内联。
什么被认为是“很多陈述”?
如果函数的地址被隐式或显式获取,编译器也无法执行内联。谁能解释一下这一点?
因为内联只是一个建议,我该如何测试哪些函数没有内联?
【问题讨论】:
这完全取决于编译器;这可能取决于优化设置、目标架构的特性(例如,函数调用的成本与由于代码大小增加而导致的缓存未命中的潜在成本)以及函数与其余代码的集成程度在特定的呼叫站点。
您可以反汇编生成的可执行文件,或要求编译器发出程序集而不是构建完成的可执行文件(使用gcc 这是-S 选项)并手动检查它。尽管如此,请注意检查优化的二进制文件并非易事——因为内联代码与调用者代码混合在一起,可能很难准确地找出内联函数的去向,同时您也可能会在非内联的副本中找到通过函数指针使用函数(如上所述)。
【讨论】:
编译器是否生成内联代码取决于 编译器。大多数现代编译器会生成很多 任何不是递归内联的东西。
这完全是错误的。获取地址后, 编译器必须为地址生成一个行外副本,但是 这并不能阻止它在函数运行时内联 调用。
你没有。
【讨论】:
完全由编译器设计者决定使用什么启发式方法来决定是否内联函数调用。希望它基于生成的代码大小而不是“语句”的数量,这是一个完全没有意义的指标。希望它还包括对性能增益的估计,以权衡代码大小的任何增加。
如果地址被占用,那么必须有一个函数的非内联实例,以便获取地址。但是,这不会阻止对函数的任何调用被内联,如果编译器决定它们应该被内联。
你可以反汇编生成的代码,看看是否有函数调用。如果调用函数很大,或者它本身内联在另一个函数中,这可能会很棘手。大多数编译器都有一种(非标准的)强制内联方式;但只有在您确定自己比编译器更了解并有测量结果证明这一点时才使用它。
【讨论】:
关于编译器何时内联的问题,请查看此线程:
Does the compiler decide when to inline my functions (in C++)?
【讨论】: