C++ 将内联方法从头文件移动到.cpp文件

C++ 将内联方法从头文件移动到.cpp文件,c++,class,methods,C++,Class,Methods,我在foo.h头文件中定义了以下类 class Foo { public: inline int Method(); }; inline int Foo::Method() { // Implementation } 现在我想将实现移到foo.cpp文件中。为此,我必须删除inline关键字,并将该方法的实现移动到foo.cpp文件中,如下所示 #include `foo.h` inline int Foo::Method() { // Implementation } 我有

我在
foo.h
头文件中定义了以下类

class Foo {

public:
    inline int Method();

};

inline int Foo::Method() { // Implementation }
现在我想将实现移到
foo.cpp
文件中。为此,我必须删除
inline
关键字,并将该方法的实现移动到
foo.cpp
文件中,如下所示

#include `foo.h`

inline int Foo::Method() { // Implementation }
我有两个问题:

  • 我关于删除
    inline
    关键字的声明正确吗?是否必须将其删除
  • 删除
    inline
    关键字通常会如何影响性能(实际上我所有的方法都是内联的)

  • 非常感谢。

    关键字
    inline
    在课堂上是多余的。如果你有一个函数体,它是隐含的

    在实现文件中,它也是相当冗余的

    它的唯一用途是在头中定义自由函数(或类外但在头中的成员函数)以避免多个实体

    在mist现代编译器上,优化是明智的,它甚至更加冗余,它们毫无疑问地嵌入任何可见的内容,或者随意忽略您的关键字

    内联用法必须一致!从7.1.2p4开始:

    内联函数应在使用odr的每个翻译单元中定义,并且在每种情况下具有完全相同的定义(3.2)。[注:内联函数的定义出现在翻译单元中之前,可能会遇到对内联函数的调用。-结束注]如果函数的定义在其第一次声明为内联之前出现在翻译单元中,则程序的格式不正确。如果使用了带有外部悬挂机构的功能 在一个翻译单元中声明内联,则应在其出现的所有翻译单元中声明内联;不需要诊断


    这可能会让人困惑,但您不应该想到
    inline
    的目的是使编译器内联成为一个函数。(就函数何时应该内联或不应该内联而言,现代编译器比您聪明得多)


    不,内联的真正目的是告诉链接器不要担心函数的多个定义。如果将(非成员)函数的定义放在标头中,则应将其标记为
    inline
    ,以避免链接器错误。

    如果将函数定义从标头移动到cpp文件,则必须删除
    inline
    关键字该函数的所有位置。对于较旧的链接器,它可能会使事情稍微变慢,但对于现代链接器,您应该注意到性能上没有真正的差异*

    在某些情况下,公共成员函数可以内联,但这只是一个坏主意。不要这样做。可以使用参数将某些私有成员函数标记为
    内联
    ,但实际上,您真正想要的是
    \uuuu属性(始终内联))
    \uu强制内联


    *在极少数情况下,它会产生影响,但99%的时候不会,剩下的99.9%你不在乎。如果测量结果显示你达到了万分之一,你可以使用前面提到的
    \u forceinline

    2。删除内联关键字通常会如何影响性能(实际上我所有的方法都是内联的)?

    inline
    关键字告诉编译器获取该函数的实现代码,并将其放置在函数调用的位置。这会减少堆栈上函数调用的数量,如果使用正确,可以提高程序的性能

    inline
    关键字只能用于小函数。Get和Set函数就是很好的例子。它们设置一个变量的值或返回一个变量的值


    如果您使用大量代码
    内联
    ,则会使代码的大小增加很多(取决于函数代码的大小以及该函数的使用次数),并实际降低程序的性能

    如果函数不是很小(或者接受几个参数,但做的事情不多,比如构造函数或类似的函数,需要做很多事情,只是将其复制到类中的某个地方),那么将其内联首先对性能几乎没有影响。setter和getter通常很适合内联,因为它们(通常)只是将数据从一个地方复制到另一个地方,并且可以在调用发生的地方轻松完成

    正如其他人所说的,这是一个“请编译,如果我可以善意地问你,考虑内联这个函数”——这不是一个“使这个函数内联”。另一方面,无论是否有
    inline
    关键字,编译器通常都将内联函数。它查看函数的大小、调用的数量以及代码从内联中得到的大小

    如果将函数移动到“foo.cpp”,它将仅内联到“foo.cpp”编译单元中(通常,编译单元=源文件)

    这就是说,除非你有一个能够进行“整个程序优化”或类似技巧的编译器,并启用该功能——这基本上意味着,编译器不会生成一个带有机器代码的现成链接对象文件,而是生成一个“已解析但未完全翻译为机器指令”的对象文件。然后,当最终将可执行文件(或共享库)放到一起时,编译器/链接器将从“中间”代码中生成一大块机器代码。MS和GCC都支持这一点,但我不知道它在大型项目中的效果如何

    编辑:

    根据Mooing Duck的评论:
    inline
    函数在对象文件中没有真正的函数名,因此链接器也可能为
    未解析的符号int Foo::Method()
    [或某种程度上的措辞]给出错误

    结束编辑

    如果性能至关重要,则应测量当前代码的性能,
    int foo() { /* do something */ }
    int foo() { /* do something else */ }
    
    struct Foo {
        void bar() { /* do something */ }
    };