【问题标题】:Inlining C++ code内联 C++ 代码
【发布时间】:2010-09-10 08:04:29
【问题描述】:

下面的代码有什么不同吗:

class Foo  
{
  inline int SomeFunc() { return 42; }
  int AnotherFunc() { return 42; }
};

这两个函数会被内联吗?内联实际上有什么不同吗?关于何时应该或不应该内联代码是否有任何规则?我经常使用AnotherFunc 语法(例如访问器),但我很少直接指定inline

【问题讨论】:

    标签: c++ inline-functions


    【解决方案1】:

    inline 关键字本质上是对编译器的提示。使用inline 并不能保证您的函数内联,也不能保证它不会。您只是让编译器知道,更努力地内联该特定函数可能是个好主意。

    【讨论】:

      【解决方案2】:

      两种表单都应该以完全相同的方式内联。对于类定义中定义的函数体,内联是隐式的。

      【讨论】:

      • 函数体隐含的内联来源是什么?我确信这不是 C++ 标准的一部分。您指的是另一个环境吗?
      • 在 C++ '03 标准中,实际引用是 9.3/2:“成员函数可以在其类定义中定义 (8.4),在这种情况下,它是内联成员函数 (7.1.2 ),..."
      【解决方案3】:

      第 33 周 Sutter 的 Guru 回答了您的一些问题以及更多问题。

      http://www.gotw.ca/gotw/033.htm

      【讨论】:

        【解决方案4】:
        class Foo  
        {
          inline int SomeFunc() { return 42; }
          int AnotherFunc() { return 42; }
        };
        

        两种方式都保证编译相同是正确的。但是,最好不要采用这两种方式。根据the C++ FAQ,您应该在类定义中正常声明它,然后在类定义之外,在标题内使用显式 inline 关键字定义它。正如FAQ所描述的那样,这是因为您想将声明和定义分开以便其他人的可读性(声明相当于“什么”和定义“如何”)。

        内联真的有什么不同吗?

        是的,如果编译器允许内联请求,那就大不相同了。将内联代码视为宏。在调用它的任何地方,函数调用都会被函数定义中的实际代码替换。如果您内联大型函数,这可能会导致代码膨胀,但如果函数太大,编译器通常会通过不授予内联请求来保护您免受这种情况的影响。

        对于何时应该或不应该内联代码是否有任何规则?

        我不知道任何硬性+快速的规则,但指导方针是仅在经常调用且相对较小的情况下内联代码。 Setter 和 getter 通常是内联的。如果它位于代码的性能特别密集的区域,则应考虑内联。永远记住你是用内联来换取可执行文件大小的执行速度。

        【讨论】:

          【解决方案5】:

          VC++ 支持__forceinline__declspec(noinline) 指令,如果你认为你比编译器更了解的话。提示:你可能不知道!

          【讨论】:

            【解决方案6】:

            内联是一个编译器提示,并不强制编译器内联代码(至少在 C++ 中)。因此,简短的回答是它是编译器,并且可能取决于您的示例中将发生的情况。大多数优秀的编译器可能会内联两者,特别是由于两个函数的常量返回明显优化。

            一般来说,内联不是您应该担心的事情。它带来了不必执行机器指令来生成堆栈帧并返回控制流的性能优势。但除了最专业的情况外,我认为这都是微不足道的。

            内联在两种情况下很重要。如果您处于实时环境中并且响应速度不够快,则可以使用。二是如果代码分析在一个非常紧凑的循环中显示出严重的瓶颈(即一个反复调用的子例程),那么内联可能会有所帮助。

            特定的应用程序和架构也可能导致您将内联作为优化。

            【讨论】:

              【解决方案7】:

              我发现一些 C++ 编译器(即 SunStudio)会抱怨如果内联被省略,就像在

              int AnotherFunc() { return 42; }
              

              所以我建议在这种情况下始终使用 inline 关键字。如果您稍后将该方法实现为实际的函数调用,请不要忘记删除 inline 关键字,这会真正搞乱链接(在 SunStudio 11 和 12 以及 Borland C++ Builder 中)。 我建议尽量少使用内联代码,因为当使用调试器单步执行代码时,即使使用“跳过”命令,它也会“进入”内联代码,这可能会很烦人。

              【讨论】:

                【解决方案8】:

                请注意,在类之外,inline 在代码中做了一些更有用的事情:通过强制(嗯,有点)C++ 编译器在每次调用函数时生成内联代码,它可以防止多个定义不同翻译单元中的相同符号(函数签名)。

                因此,如果您在头文件中内联非成员函数,并将其包含在多个 cpp 文件中,则链接器不会对您大喊大叫。如果函数太大而无法建议内联,请使用 C 方式:在 header 中声明,在 cpp 中定义。

                这与代码是否真的内联无关:它允许在头文件中实现样式,这对于短成员函数很常见。

                (如果编译器需要函数的非内联渲染,我想编译器会很聪明,就像模板函数一样,但是......)

                【讨论】:

                  【解决方案9】:

                  另外补充一下 Greg 所说的,在执行优化时(即inline-ing),编译器不仅会参考代码中的关键字,还会参考其他命令行参数,以指定编译器应如何优化代码。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-03-17
                    • 2013-04-26
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-08-16
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多