什么时候我应该写关键字内联的函数/方法在c++ ?
在看到一些答案后,一些相关的问题:
在c++中,什么时候我不应该为函数/方法写关键字“内联”? 什么时候编译器不知道什么时候使一个函数/方法'内联'? 当一个应用程序为一个函数/方法写“内联”时,它是否重要?
什么时候我应该写关键字内联的函数/方法在c++ ?
在看到一些答案后,一些相关的问题:
在c++中,什么时候我不应该为函数/方法写关键字“内联”? 什么时候编译器不知道什么时候使一个函数/方法'内联'? 当一个应用程序为一个函数/方法写“内联”时,它是否重要?
当前回答
你要把它放在最开始,在返回类型之前。但是大多数编译器忽略了它。如果它是定义的,并且它的代码块较小,大多数编译器都认为它是内联的。
其他回答
什么时候编译器不知道什么时候使一个函数/方法'内联'?
这取决于所使用的编译器。不要盲目相信现在的编译器比人类更了解如何内联,也不要因为性能原因而使用它,因为它是链接指令而不是优化提示。虽然我同意这些观点在意识形态上是正确的,但遇到现实可能是另一回事。
在阅读了多个线程之后,出于好奇,我尝试了内联对我正在工作的代码的影响,结果是我得到了GCC的可测量加速,而英特尔编译器的速度没有提高。
(更多细节:数学模拟与少数关键函数定义类之外,GCC 4.6.3 (g++ -O3), ICC 13.1.0 (icpc -O3);将内联添加到临界点导致GCC代码加速6%)。
因此,如果你将GCC 4.6限定为现代编译器,那么如果你编写CPU密集型任务,并且知道瓶颈在哪里,内联指令仍然很重要。
在开发和调试代码时,不要使用内联。这会使调试复杂化。
添加它们的主要原因是为了帮助优化生成的代码。通常,这是以增加的代码空间换取速度,但有时内联可以同时节省代码空间和执行时间。
在算法完成之前将这种思想扩展到性能优化是不成熟的优化。
什么时候应该内联:
1.当人们想要避免调用函数时发生的开销,如参数传递,控制传递,控制返回等。
2.函数应该很小,经常被调用,并且内联是非常有利的,因为根据80-20规则,尽量使那些对程序性能有重大影响的函数内联。
正如我们所知,内联只是一个请求编译器类似于注册,它将花费你在对象代码大小。
你要把它放在最开始,在返回类型之前。但是大多数编译器忽略了它。如果它是定义的,并且它的代码块较小,大多数编译器都认为它是内联的。
我想用一个令人信服的例子来解释这篇文章中所有的伟大答案,以消除任何剩余的误解。
给定两个源文件,例如:
inline111.cpp: # include < iostream > 空白栏(); Inline fun() { 返回111; } Int main() { std:: cout < <“inline111:有趣 () = " << 有趣的 () << ", & 有趣= " < < (void *)与娱乐; 酒吧(); } inline222.cpp: # include < iostream > Inline fun() { 返回222; } 空格条(){ std:: cout < <“inline222:有趣 () = " << 有趣的 () << ", & 有趣= " < < (void *)与娱乐; }
Case A: Compile: g++ -std=c++11 inline111.cpp inline222.cpp Output: inline111: fun() = 111, &fun = 0x4029a0 inline222: fun() = 111, &fun = 0x4029a0 Discussion: Even thou you ought to have identical definitions of your inline functions, C++ compiler does not flag it if that is not the case (actually, due to separate compilation it has no ways to check it). It is your own duty to ensure this! Linker does not complain about One Definition Rule, as fun() is declared as inline. However, because inline111.cpp is the first translation unit (which actually calls fun()) processed by compiler, the compiler instantiates fun() upon its first call-encounter in inline111.cpp. If compiler decides not to expand fun() upon its call from anywhere else in your program (e.g. from inline222.cpp), the call to fun() will always be linked to its instance produced from inline111.cpp (the call to fun() inside inline222.cpp may also produce an instance in that translation unit, but it will remain unlinked). Indeed, that is evident from the identical &fun = 0x4029a0 print-outs. Finally, despite the inline suggestion to the compiler to actually expand the one-liner fun(), it ignores your suggestion completely, which is clear because fun() = 111 in both of the lines.
Case B: Compile (notice reverse order): g++ -std=c++11 inline222.cpp inline111.cpp Output: inline111: fun() = 222, &fun = 0x402980 inline222: fun() = 222, &fun = 0x402980 Discussion: This case asserts what have been discussed in Case A. Notice an important point, that if you comment out the actual call to fun() in inline222.cpp (e.g. comment out cout-statement in inline222.cpp completely) then, despite the compilation order of your translation units, fun() will be instantiated upon it's first call encounter in inline111.cpp, resulting in print-out for Case B as inline111: fun() = 111, &fun = 0x402980.
Case C: Compile (notice -O2): g++ -std=c++11 -O2 inline222.cpp inline111.cpp or g++ -std=c++11 -O2 inline111.cpp inline222.cpp Output: inline111: fun() = 111, &fun = 0x402900 inline222: fun() = 222, &fun = 0x402900 Discussion: As is described here, -O2 optimization encourages compiler to actually expand the functions that can be inlined (Notice also that -fno-inline is default without optimization options). As is evident from the outprint here, the fun() has actually been inline expanded (according to its definition in that particular translation unit), resulting in two different fun() print-outs. Despite this, there is still only one globally linked instance of fun() (as required by the standard), as is evident from identical &fun print-out.