【发布时间】:2013-04-15 16:53:44
【问题描述】:
编译器什么时候不一定要把内联标记为内联的函数?
【问题讨论】:
-
对于现代编译器,这可能不是二元选择。众所周知,现代编译器会拆分函数,并且内联的决定可以是分开的。例如。由于假定异常很少见,编译器只能内联函数的非异常部分。
标签: c++ performance inline
编译器什么时候不一定要把内联标记为内联的函数?
【问题讨论】:
标签: c++ performance inline
最明显的是,当您使用指向函数的指针时,它不能内联该函数。如果您传递指针并且(可能稍后)决定通过指针调用函数,编译器必须生成函数的非内联版本。当然,如果直接调用函数,编译器可能仍然内联它。而且编译器也可以随意不内联函数。
【讨论】:
使用inline 关键字只是对编译器的提示,您建议在使用的地方内联扩展它。然而,在预测 L1 和 L2 缓存以及分支预测管道等高级 CPU 功能可能对性能产生影响时,编译器比您以往任何时候都智能得多。如果编译器决定内联函数会使代码变慢,或者不可接受地变大,它就不会内联它。或者,如果它只是因为语法依赖而无法实现,例如其他代码使用函数指针进行回调,或者像在动态/静态代码库中那样将函数导出到外部。
更多解释请参见here。
【讨论】:
如果问题是编译器无法以任何方式内联函数,那么有几个答案。
定义后,如果函数是递归的,其递归级别取决于参数,而不是尾递归,则不能内联(在编译时不可能知道函数的迭代次数)。通常,不显示尾递归的递归函数不会被内联(即使在编译器可以推断出递归步骤数的情况下)。
在看不到指针初始化的上下文中通过指针使用时。
如果问题不是什么时候保证不被内联,而是什么东西可以让编译器避免内联,还有一些其他的。例如,函数的复杂性和大小,它是否有循环,它已经在做的内联级别(f调用g调用h调用i......所有这些都可能被内联,但编译器倾向于放弃如果通话次数足够多)....还有其他的。您可以尝试从您的编译器供应商那里了解他们运行什么类型的启发式方法来确定何时内联。
【讨论】: