我被告知编译器会忽略inline
或__inline
个关键字,除非另有说明VS.
所以我想写这样的代码:
class A {
public:
inline A() {
P(); //yep, works
}
inline void P() {
}
}
而不是像这样分开它:
//.h
class A {
public:
A();
void P();
}
//.cpp
#include ".h"
A::A() {
P();
}
void A::P() {
}
出于纯粹的懒惰和对C#的爱。
所以问题是:即使在每种现有情况下的优化方面,它们是否同样有效?除了内联函数之外,内联关键字没有其他角色了吗?
答案 0 :(得分:4)
你的问题有一些误解:
inline
实际上具有与优化无关的效果:它允许多个定义(以便您可以将内联定义放在包含在多个编译单元中的标头中)。inline
。因此,在这些定义上写关键字毫无意义。至于性能:实际上存在差异,因为在第一种情况下,定义在包含头文件的编译单元中是可见的(因此方法可以内联),而在后者中 - 假设你没有&#39 ; t具有链接时优化 - 定义不可见,无法内联或以其他方式分析。这是一个相当小的优点:大多数C和C ++代码都很好地留下99%的函数和#34;非内联"。此外,还有缺点(代码膨胀,icache压力,编译时间增加),因此不要将此作为在头文件中编写方法定义的理由。将它写在实现文件中并且只导出声明是C ++中的标准方法,并且具有C#经验并不是偏离此标准的好理由。
答案 1 :(得分:3)
是的,编译器可能会选择忽略inline
,但有充分的理由:内联可能会大大减慢您的程序速度。内联意味着更大的代码大小,这意味着CPU的指令缓存更加紧张,这意味着更低的性能。编译器编写者知道这一点,因此有inline
提示要遵循的启发式方法,而不是。
虽然您可以将所有内容放在C ++中的头文件中,但这样做并不是一个好主意:
即使这样也不会强制内联。编译器仍然必须在目标文件中发出该函数,并且链接器具有抛弃副本的工作。你在编译时付出了代价,并得到很少的回报。
更改.cpp文件中的代码时,只能重新编译该文件;更改标题时,必须重新编译所有相关文件。如果所有内容都在标题中,那么您始终必须将程序构建为一个巨大的整体块。对于大型项目,这大大降低了测试 - 更改 - 构建周期的频率,使您的工作效率降低。
我强烈建议你接受C / C ++中标题和实现文件之间的区别,这真的是节省了大量时间。
答案 2 :(得分:1)
编译器可以选择忽略inline
。
这并不意味着它完全忽略了inline
,它只是将其作为提示。
当你把所有内容都设置为内联时,你可能会得到一个更大的编译文件,因为内联的内容比通常情况要多得多。
你也用C ++而不是C#写作,所以纯粹的懒惰和对C#的热爱并不是编写糟糕的C ++代码的借口。
答案 3 :(得分:1)
如果方法定义和调用者位于不同的编译单元(.cpp文件)中,则GCC无法内联方法。所以你需要将定义放在标题中。
如果启用了链接时间代码生成,Visual Studio可能会内联它,默认情况下为/ O3。
在这两种情况下,请注意,与C相比,“inline”关键字在C ++中的含义发生了变化。它现在具有语义含义,而不是内联提示。
您可以在Visual Studio中使用__forceinline来强制内联 - 实际上它可以在语义上可行的所有情况下使用。
对于GCC,您可以使用属性((always_inline)),但GCC并不总是遵守它 - 它仍会影响代码大小(与Visual Studio不同,它始终遵守它)。