6

很久以前有人告诉我,通过使用关键字inline并在头文件中写入主体来制作通常被内联调用的简短函数/方法。这是为了优化代码,这样实际的函数调用就不会产生开销。

今天看起来怎么样?现代编译器(在这种情况下为 Visual Studio 2010)是否会自动内联这些短函数,还是自己仍然“有必要”这样做?

4

7 回答 7

7

inline一直是对编译器的提示,而如今,编译器在这方面大部分是自己做出决定的(请参阅 参考资料register)。

为了内联扩展函数,编译器必须看到该函数的定义。对于只在一个翻译单元中定义和使用的函数,这没问题:在使用之前将定义放在某个地方,编译器将决定是否内联该函数。

对于在多个翻译单元中使用的函数,为了让编译器看到函数的定义,定义必须放在头文件中。当您这样做时,您需要标记该函数inline以告诉编译器和链接器该函数有多个定义是可以的。(好吧,我想你可以制作这个函数static,但是你最终可能会浪费多个副本的空间)

于 2012-09-13T20:26:05.927 回答
4

启用警告C4710,如果您定义为内联的函数没有被编译器内联,这将警告您。

启用警告C4711,如果编译器内联未指定用于内联的函数,这将警告您。

这两个警告的组合将使您更好地了解编译器实际上对您的代码做了什么,以及是否值得手动指定内联函数。

于 2012-09-13T20:25:38.077 回答
3

一般来说,inline现在更多地使用关键字来允许您在头文件中定义函数时“违反”一个定义规则,而不是给编译器关于内联的提示。许多编译器非常擅长决定何时内联函数,只要函数体在调用点可见。

当然,如果您仅在非内联源文件中定义函数,编译器将能够将其内联在该源文件中,但不能在任何其他翻译单元中。

于 2012-09-13T20:24:35.660 回答
2

在以下情况下,编译器可以进行内联:

  1. 您将函数标记为inline

    1. 它在当前翻译单元或包含在其中的文件中定义;
    2. 编译器认为值得这样做。根据MSDN

      inline关键字告诉编译器内联扩展是首选
      编译器将内联扩展选项和关键字视为建议。

  2. 您使用了__forceinline关键字(或__ attribute __((always_inline))在 gcc 中)。这将使编译器跳过一些检查并为您进行内联。

    关键字覆盖了成本/收益分析,__forceinline而是依赖于程序员的判断。

  3. 如果您通过将标志传递给编译器或链接器来打开链接时代码生成, Microsoft 编译器也可以执行跨模块内联。进行这样的优化非常聪明:尝试检查使用./GL/LTCG/LTCG

请注意,如果您的函数是,则永远不会发生内联:

  • 递归的;
  • 通过指向它的指针调用。
于 2012-09-14T10:32:37.317 回答
1

简而言之,是的,编译器将决定您的函数是否变为inline. 你可以检查这个问题:

编译器是否决定何时内联我的函数(在 C++ 中)?

于 2012-09-13T20:24:14.567 回答
1

是的,现代编译器将(取决于各种配置选项)自动选择内联函数,即使它们位于源文件(而不是头文件)中。使用 inline 指令可以给出提示。

于 2012-09-13T20:21:13.193 回答
1

除了你的主要观点(在代码中放置多少内联指令对今天的编译器有用),请记住内联函数只是对编译器的提示,不一定被编译为内联。

于 2012-09-13T20:23:33.740 回答