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 */ }
};