什么时候编译器内联C ++代码?

时间:2009-09-18 11:32:21

标签: c++ optimization compiler-construction inline

在C ++中,如果方法是显式声明inline(或在头文件中定义),或者允许编译器在他们认为合适的情况下内联方法,那么方法是否只有内联?

11 个答案:

答案 0 :(得分:35)

内联关键字实际上只是告诉链接器(或告诉编译器告诉链接器)同一函数的多个相同定义不是错误。如果要在标头中定义函数,则需要它,否则如果标头包含在多个编译单元中,您将从链接器中获得“多重定义”错误。

选择内联作为关键字的理由似乎是人们想要在头文件中定义(非模板)函数的唯一原因是它可以由编译器内联。除非具有完整定义,否则编译器不能内联函数调用。如果函数没有在头文件中定义,编译器只有声明,即使它想要也不能内联函数。

如今,我听说,不仅是编译器优化了代码,而且链接器也能做到这一点。即使函数未在同一个编译单元中定义,链接器也可以(如果它们没有这样做)内联函数调用。

如果有的话,在头文件中定义大于单行的函数可能不是一个好主意(编译时间不好,如果内联大函数,可能会导致膨胀和性能下降)。 / p>

答案 1 :(得分:24)

是的,编译器可以内联代码,即使代码没有明确声明为inline

基本上,只要语义没有改变,编译器就可以虚拟地对生成的代码做任何想做的事情。该标准不会对生成的代码强加任何特殊内容。

答案 2 :(得分:5)

编译器可能会内联任何函数,也可能不会内联它。他们被允许使用inline装饰作为这个决定的提示,但他们也被允许忽略它。

另请注意,如果类成员函数在类定义中正确定义,则它们具有隐式inline修饰。

答案 3 :(得分:4)

如果我没有弄错,当启用优化时,编译器将内联任何合适的例程或方法。

答案 4 :(得分:4)

编译器可能会忽略您的内联声明。它基本上被编译器用作提示,以决定是否这样做。编译器没有义务内联标记为内联的内容,或者不内联不内联的内容。基本上你受编译器和你选择的优化级别的支配。

答案 5 :(得分:3)

来自IBM信息中心的文字,

  

使用内联说明符只是一个   建议编译器一个   可以执行内联扩展;该   编译器可以自由忽略   建议。

     

C语言任何函数(main除外)都可以声明或   定义为内联内联   函数说明符。静态本地   不允许变量   在内联体内定义   功能

     在类声明中实现的

C ++ 函数是   自动定义内联。定期   C ++函数和成员函数   在课堂外宣布   声明,但除外   main,可以声明或定义为   内联函数内联   符。静态本地和字符串   在一个体内定义的文字   内联函数被视为   翻译单位的相同对象;

答案 6 :(得分:2)

您的编译器文档应该告诉您,因为它依赖于实现。例如,除非应用优化,否则GCC根据其手册从不内联任何代码。

如果编译器没有内联代码, inline 关键字将与 static 具有相同的效果,并且调用代码的每个编译单元都有自己的副本。智能链接器可以将这些缩减为单个副本。

答案 7 :(得分:1)

如果内联不违反代码语义并且它可以到达功能代码,编译器可以内联它想要的内容。它也可以有选择地内联 - 当感觉它是一个好主意时进行内联,而当它感觉不是一个好主意或者它会违反代码语义时不内联。

即使函数位于另一个转换单元中,某些编译器也可以进行内联 - 这就是所谓的链接时代码生成。

内联时违反代码语义的典型情况是虚拟调用并将函数地址传递给另一个函数或存储它。

答案 8 :(得分:1)

编译器按照自己的意愿进行优化,除非你指明相反的情况。

答案 9 :(得分:0)

inline关键字只是对编译器的请求。编译器保留在线创建或不创建函数的权利。推动编译器决策的一个主要因素是代码的简单性(不是很多循环)

默认情况下,成员函数是内联声明的。(编译器也在这里决定)

这些不是硬性规定。它根据编译器实现而有所不同。

如果有人知道其他因素,请发帖。

答案 10 :(得分:0)

内联扩展可能不起作用的一些情况是:

  1. 对于返回值的函数,如果存在循环,开关或goto
  2. 对于不返回值的函数,如果退出语句退出;
  3. 如果函数包含静态变量
  4. 如果内联函数是递归的。
  5. 内联扩展使程序运行得更快,因为消除了函数调用和return语句的开销。但是,它使程序占用更多内存,因为定义内联函数的语句在调用函数的每个点都被重现。因此,需要进行权衡。

    (如我的一本OOP书中所述)