Pau*_*nta 14 c++ compiler-construction inline function
假设我有一些函数,每个函数大约有两行简单的代码,他们互相称呼:A调用B调用C调用D...调用K.(所以基本上它是一系列短函数调用.)编译器通常会在调用树中深入内联这些函数有多深?
Mat*_* M. 13
这个问题没有意义.
如果你考虑内联及其后果,你会意识到:
在决定是否内联时,编译器因此在创建的潜在膨胀和预期的速度增益之间执行平衡动作.这种平衡行为受到选项的影响:对于gcc -O3意味着优化速度,同时-Oz意味着优化尺寸,内联它们具有准相反的行为!
因此,重要的不是"嵌套级别",而是指令的数量(可能加权,因为并非所有指令都相等).
这意味着一个简单的转发功能:
int foo(int a, int b) { return foo(a, b, 3); }
Run Code Online (Sandbox Code Playgroud)
从内联的角度看,它基本上是"透明的".
另一方面,计算一百行代码的函数不太可能被内联.除了static只调用一次的自由函数是准系统内联的,因为在这种情况下它不会产生任何重复.
从这两个例子中我们可以预见到启发式行为的表现:
在那之后,它们是您应该能够设置为影响某种或那种方式的参数(MSVC __force_inline强烈暗示inling,gcc因为它们-finline-limit标记为"提高"指令计数的阈值等等)
切线:你知道部分内联吗?
它是在4.6中的gcc中引入的.顾名思义,这个想法是部分内联函数.通常,当函数被"保护"并且可能(在某些情况下)几乎立即返回时,避免函数调用的开销.
例如:
void foo(Bar* x) {
if (not x) { return; } // null pointer, pfff!
// ... BIG BLOC OF STATEMENTS ...
}
void bar(Bar* x) {
// DO 1
foo(x);
// DO 2
}
Run Code Online (Sandbox Code Playgroud)
可以"优化"为:
void foo@0(Bar* x) {
// ... BIG BLOC OF STATEMENTS ...
}
void bar(Bar* x) {
// DO 1
if (x) { foo@0(x); }
// DO 2
}
Run Code Online (Sandbox Code Playgroud)
当然,内联的启发式再次适用,但它们更适用于歧视!
最后,除非您使用WPO(整个程序优化)或LTO(链接时间优化),否则只有在定义与调用站点相同的TU(转换单元)时才能内联函数.
我见过编译器内联超过5个函数.但在某些时候,它基本上变成了编译器所做的空间效率权衡.每个编译器在这方面都不同.Visual Studio非常保守,内联.GCC(在-O3下)和英特尔编译器喜欢内联......