我在foo.h头文件中定义了以下类
class Foo {
public:
inline int Method();
};
inline int Foo::Method() { // Implementation }
Run Code Online (Sandbox Code Playgroud)
我现在想将实现移动到一个foo.cpp文件.为此,我必须删除inline关键字并将方法的实现移动到这样的foo.cpp文件
#include `foo.h`
inline int Foo::Method() { // Implementation }
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
inline关键字的声明是否正确?是否必须删除?inline关键字会影响性能(实际上我的所有方法都是内联的)?非常感谢你提前.
Moo*_*uck 16
如果将函数定义从标题移动到cpp文件,则必须删除该函数的inline所有所有位置的关键字.使用较旧的连接器可能会使事情稍微变慢,但使用现代连接器时,您应该注意到性能没有真正的差异.*
在某些情况下,公共成员职能可以inline,但这只是一个坏主意.不要这样做.参数可以用来标记某些私有成员函数inline,但实际上你真正想要的是那些__attribute__((always_inline))或者__forceinline
*在极少数情况下,它会有所作为,但99%的时间不会,99.9%的你不在乎.如果测量显示您达到了千分之一,那么您可以使用前述的__forceinline.
关键字inline在课堂上是多余的.如果你有一个功能体,就暗示了这一点.
在实现文件中,它也是相当多余的.
它的唯一用途是,如果您在标题(或类外的成员函数,但在标题中)中定义一个自由函数,以避免多个实体.
雾现代编译器的优化方面更加冗余,他们无论如何都可以毫无疑问地内联任何内容,或者随意忽略您的关键字.
内联使用必须一致!从7.1.2p4开始:
内联函数应在每个使用过的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2).[注意:在定义出现在翻译单元之前,可能会遇到对内联函数的调用.-end note]如果函数的定义在第一次声明为内联之前出现在翻译单元中,则程序格式错误.如果在一个翻译单元中内联声明具有外部链接的功能,则应在其出现的所有翻译单元中内联声明; 无需诊断....
您和这里提供有关小型功能建议的人正在寻找inline老式的方法。
inline过去的意思是“我希望这段代码能够快速运行,所以每当我调用这个函数时,我希望你就地扩展它以避免函数调用的开销。”
这确实是一个很好的优化。事实上,它非常好,即使您不指定 ,编译器也会急切地执行此操作inline。
编译器也可以自由地不扩展你的inline功能。所以你真的不必担心它会如何影响性能,因为inline如果你以愚蠢的方式使用它,编译器可以并且会忽略它。
事实上,今天的编译器几乎总是忽略您对 的使用inline,而只是做他们认为最好的事情。
那么,既然知道了这一点,为什么人们仍然使用 呢inline?
现在使用它的原因只有一个inline,那就是绕过单一定义规则 (ODR)。
在 C/C++ 中,您只能定义一个函数一次。如果你这样做:
int foo() { /* do something */ }
int foo() { /* do something else */ }
Run Code Online (Sandbox Code Playgroud)
编译器会抱怨你已经定义了同一个函数两次。
这看起来像一个愚蠢的例子,但当你使用时,做这样的事情特别容易#include- 如果你在标头中定义你的函数,并且你使用#include相同的标头两次,这正是你正在做的事情。
值得庆幸的是,inline它还有另一种用途,至今仍然有效:如果将函数标记为inline,它会强制编译器消除 ODR 问题,从而可以在标头中定义函数。
换句话说,inline现在意味着“我想在标头中定义这个函数”。
当您这样看时,应该很清楚,inline在将函数移动到 cpp 文件中时应该删除 。
出于兴趣考虑,有几个地方函数被隐式地内联。其中之一是类成员函数:
struct Foo {
void bar() { /* do something */ }
};
Run Code Online (Sandbox Code Playgroud)
我见过人们像这样标记函数inline,但这完全是多余的。无论如何,编译器都会这样做;无需担心 ODR,也无需获得任何性能。
另一个地方是在模板中。由于模板必须在标头中定义,因此它们不受 ODR 的约束,并且inlineing 它们是多余的。