在 C++ 中,方法是否仅在显式声明(或在头文件中定义)时才被内联inline
,还是允许编译器在他们认为合适的情况下内联方法?
11 回答
inline关键字实际上只是告诉链接器(或告诉编译器告诉链接器)同一函数的多个相同定义不是错误。如果要在标头中定义函数,则需要它,或者如果标头包含在多个编译单元中,则链接器会出现“多重定义”错误。
选择inline作为关键字的理由似乎是,人们想要在头文件中定义(非模板)函数的唯一原因是它可以被编译器内联。编译器不能内联函数调用,除非它具有完整的定义。如果函数没有在头文件中定义,编译器只有声明,即使它想内联也不能内联函数。
现在,我听说,优化代码的不仅是编译器,链接器也可以做到这一点。即使函数没有在同一个编译单元中定义,链接器也可以(如果他们还没有这样做的话)内联函数调用。
如果在头文件中定义大于单行的函数可能不是一个好主意(不利于编译时间,如果内联大函数,可能会导致膨胀和性能下降)。
是的,编译器可以内联代码,即使它没有明确声明为inline
.
基本上,只要语义没有改变,编译器几乎可以对生成的代码做任何它想做的事情。该标准不强制对生成的代码进行任何特殊处理。
编译器可能内联任何函数,也可能不内联它。他们被允许使用inline
装饰作为这个决定的提示,但他们也被允许忽略它。
另请注意,如果类成员函数inline
在类定义中正确定义,则它们具有隐式修饰。
如果我没记错的话,当优化打开时,编译器会内联任何合适的例程或方法。
编译器可能会忽略您的内联声明。它基本上被编译器用作提示,以决定是否这样做。编译器没有义务内联标记为内联的内容,或者不内联没有内联的内容。基本上,您受编译器和您选择的优化级别的支配。
来自IBM信息中心的文本,
使用 inline 说明符只是对编译器的一个建议,即可以执行内联扩展;编译器可以随意忽略该建议。
C 语言除 main 之外的任何函数都可以使用 inline 函数说明符声明或定义为内联。不允许在内联函数体内定义静态局部变量。
在类声明中实现的C++函数是自动内联定义的。在类声明之外声明的常规 C++ 函数和成员函数(main 除外)可以使用 inline 函数说明符声明或定义为内联。在内联函数体中定义的静态局部变量和字符串字面量在翻译单元中被视为同一个对象;
您的编译器文档应该告诉您,因为它依赖于实现。例如,GCC 根据其手册从不内联任何代码,除非应用了优化。
如果编译器不内联代码,则inline关键字的作用与static相同,每个调用代码的编译单元都有自己的副本。智能链接器可以将这些减少到单个副本。
编译器可以内联任何它想要的内容,以防内联不违反代码语义并且它可以到达函数代码。它还可以有选择地内联——当它认为这是一个好主意时进行内联,而当它不认为这是一个好主意或违反代码语义时不进行内联。
即使函数在另一个翻译单元中,一些编译器也可以进行内联 - 这称为链接时代码生成。
内联违反代码语义的典型情况是虚拟调用并将函数地址传递给另一个函数或存储它。
除非您指定相反,否则编译器会根据需要进行优化。
inline 关键字只是对编译器的请求。编译器保留制作或不制作内联函数的权利。驱动编译器决定的主要因素之一是代码的简单性(循环不多)
默认情况下,成员函数是内联声明的。(编译器也在这里决定)
这些不是硬性规定。它根据编译器实现而有所不同。
如果有人知道涉及其他因素,请发布。
内联扩展可能不起作用的一些情况是:
- 对于返回值的函数,如果存在循环、开关或 goto
- 对于不返回值的函数,如果返回语句退出;
- 如果函数包含静态变量
- 如果内联函数是递归的。
内联扩展使程序运行得更快,因为消除了函数调用和返回语句的开销。但是,它会使程序占用更多内存,因为定义内联函数的语句会在调用函数的每个点处重现。因此,需要权衡取舍。
(如我的一本 OOP 书籍中所述)