说我有一些功能,每个代码大约两个简单的线条,和他们互相称呼这样的:A
电话B
电话C
调用D
...调用K
。 (所以基本上这是一系列短的函数调用。)编译器通常会在调用树中嵌入这些函数多深?编译器内联函数有多深?
回答
的问题是没有意义的。
如果你仔细想想内联,而其后果,你就会意识到这一点:
- 避免了函数调用(与所有的寄存器保存/帧调整)
- 自曝更多背景信息优化(死了商店,死码,公共子表达式elimintation ...)
- 重复码(腹胀指令缓存和可执行文件的大小,除其他事项外)
决定当无论是否内联,编译器都会在潜在的膨胀和预期的速度增益之间执行平衡操作。这种平衡行为受到选项的影响:对于gcc -O3
意味着优化速度,而-Oz
意味着对尺寸进行优化,在内联时它们具有准相反的行为!
因此,重要的不是“嵌套层次”是指令的数量(可能加权因为不是所有的都是一样的)。
这意味着,一个简单的转发功能:
int foo(int a, int b) { return foo(a, b, 3); }
是从视点内联基本上是“透明的”。
另一方面,计算一百行代码的函数不太可能被内联。除了一次只调用一次的自由函数是准系统内联的,因为它在这种情况下不会造成任何重复。
从这两个例子,我们得到的启发是如何表现一种预感:
- 少的指令功能有,用于inling
- 的次数越少就越好叫法,内联 更好
在那之后,他们的参数,你应该能够设置影响这种或那种方式(MSVC为__force_inline
强烈的inling暗示,gcc
因为他们-finline-limit
标志,以“提高”的tresh旧的指令数等...)
在切线:你知道部分内联?
它是在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
}
可以得到 “优化” 为:
void [email protected](Bar* x) {
// ... BIG BLOC OF STATEMENTS ...
}
void bar(Bar* x) {
// DO 1
if (x) { [email protected](x); }
// DO 2
}
当然,再次为内联启发式申请,但他们更多的申请有差别!
最后,除非你使用WPO(全程序优化)或LTO(链接时间优化)功能只能如果他们的定义是相同的TU(翻译单元)内联该调用点。
我通常不会这样做,但我认为我应该改变接受的答案。 :)我不知道部分内联,也不知道基于调用次数的内联。感谢细节。 –
我见过编译器内联多于5个函数。但在某种程度上,它基本上成为编译器所做的空间效率权衡。每个编译器在这方面都有所不同。 Visual Studio对于内联非常保守。 GCC(-O3下)和英特尔编译爱内联......
- 1. C/C++编译器可以内联malloc()内联函数吗?
- 2. 当内联函数的编译过程
- 3. 内联函数代码不能编译
- 4. 为什么Delphi编译器不内联汇编函数?
- 5. 是否有内联网页编译器?
- 6. C51 C编译器内联汇编到SDCC内联汇编
- 7. 静态模板函数可以通过编译器内联吗?
- 8. 编译器是否决定何时内联函数(使用C++)?
- 9. 编译器如何处理内联导出函数?
- 10. 谷歌封闭编译器 - 不内联goog lib函数调用?
- 11. 编译器如何管理返回内联函数?
- 12. 编译器是否会在没有主体的情况下内联函数?
- 13. 编译器内联比内联手动更好吗?
- 14. ç内联汇编帮助(数字火星C编译器)
- 15. VB.NET或C#中的内联函数和条件编译?
- 16. 与模板内联函数编译错误
- 17. 在使用-O3编译时将函数标记为内联?
- 18. 修改内联样式,多元素深
- 19. 检查一个特定函数是否内联英特尔编译器
- 20. 为什么不将编译器内联函数写入不同的源文件?
- 21. 编译器会忽略我的函数的内联限定符吗?
- 22. 为什么编译器坚持我的函数是内联的呢?
- 23. Can/do C编译器能够优化内联函数的地址吗?
- 24. 编译器如何决定是否值得让我的函数内联?
- 25. 现在的C++编译器内联函数只能调用一次吗?
- 26. Linux内核2.4.32编译中多种函数的多重定义
- 27. Java编译器是否有效地处理内联字符串?
- 28. 使用SSE2内在函数和gcc内联汇编器
- 29. 将编译器与编辑器关联
- 30. 内联函数
您可以简单地测试并查看程序集!您的编译器文档应该告诉您如何指定内联深度;我认为默认情况下GCC的值大概是50。 –
我相信这应该是编译器特定的,并且不会发布编译器的信息。 –
在MSVC下,您可以使用'#pragma inline_depth'(http://msdn.microsoft.com/zh-cn/library/cx053bca.aspx)对此进行部分控制,尽管在某些情况下我遇到了问题(例如递归内联,这是有可能的,但从来没有工作,最终做手工) – Necrolis