很久以前有人告诉我,通过使用关键字inline并在头文件中写入主体来制作通常被内联调用的简短函数/方法。这是为了优化代码,这样实际的函数调用就不会产生开销。
今天看起来怎么样?现代编译器(在这种情况下为 Visual Studio 2010)是否会自动内联这些短函数,还是自己仍然“有必要”这样做?
很久以前有人告诉我,通过使用关键字inline并在头文件中写入主体来制作通常被内联调用的简短函数/方法。这是为了优化代码,这样实际的函数调用就不会产生开销。
今天看起来怎么样?现代编译器(在这种情况下为 Visual Studio 2010)是否会自动内联这些短函数,还是自己仍然“有必要”这样做?
inline
一直是对编译器的提示,而如今,编译器在这方面大部分是自己做出决定的(请参阅 参考资料register
)。
为了内联扩展函数,编译器必须看到该函数的定义。对于只在一个翻译单元中定义和使用的函数,这没问题:在使用之前将定义放在某个地方,编译器将决定是否内联该函数。
对于在多个翻译单元中使用的函数,为了让编译器看到函数的定义,定义必须放在头文件中。当您这样做时,您需要标记该函数inline
以告诉编译器和链接器该函数有多个定义是可以的。(好吧,我想你可以制作这个函数static
,但是你最终可能会浪费多个副本的空间)
一般来说,inline
现在更多地使用关键字来允许您在头文件中定义函数时“违反”一个定义规则,而不是给编译器关于内联的提示。许多编译器非常擅长决定何时内联函数,只要函数体在调用点可见。
当然,如果您仅在非内联源文件中定义函数,编译器将能够将其内联在该源文件中,但不能在任何其他翻译单元中。
在以下情况下,编译器可以进行内联:
您将函数标记为inline
和
该
inline
关键字告诉编译器内联扩展是首选。
编译器将内联扩展选项和关键字视为建议。
您使用了__forceinline
关键字(或__ attribute __((always_inline))
在 gcc 中)。这将使编译器跳过一些检查并为您进行内联。
关键字覆盖了成本/收益分析,
__forceinline
而是依赖于程序员的判断。
如果您通过将标志传递给编译器或链接器来打开链接时代码生成, Microsoft 编译器也可以执行跨模块内联。进行这样的优化非常聪明:尝试检查使用./GL
/LTCG
/LTCG
请注意,如果您的函数是,则永远不会发生内联:
简而言之,是的,编译器将决定您的函数是否变为inline
. 你可以检查这个问题:
是的,现代编译器将(取决于各种配置选项)自动选择内联函数,即使它们位于源文件(而不是头文件)中。使用 inline 指令可以给出提示。
除了你的主要观点(在代码中放置多少内联指令对今天的编译器有用),请记住内联函数只是对编译器的提示,不一定被编译为内联。