你可以在这里看到区别:
https://godbolt.org/
假设你有以下代码(你的代码无法编译:缺少
;
和
[]
):
struct Point
{
inline float x() const { return v[0]; }
inline float y() const { return v[1]; }
inline float z() const { return v[2]; }
float v[3];
};
int main() {
Point myPoint;
myPoint.v[0] = 5;
float myVal = myPoint.x() + 5;
return myVal;
}
然后gcc 9.2发布:
Point::x() const:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
movss xmm0, DWORD PTR [rax]
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
movss xmm0, DWORD PTR .LC0[rip]
movss DWORD PTR [rbp-16], xmm0
lea rax, [rbp-16]
mov rdi, rax
call Point::x() const
movss xmm1, DWORD PTR .LC0[rip]
addss xmm0, xmm1
movss DWORD PTR [rbp-4], xmm0
movss xmm0, DWORD PTR [rbp-4]
cvttss2si eax, xmm0
leave
ret
.LC0:
.long 1084227584
我在阅读汇编代码方面并不是很熟练,但我认为将上述内容与使用-O3
的输出结果进行比较 已经足够有说服力了:
main:
mov eax, 10
ret
生成的代码可能会因上下文而有很大的变化,我只是想知道是否有任何根本原因它永远不会或总会发生。
上面的例子已经证明了“永远不会”的错误。然而,“总是”很难实现。您得到的保证是,生成的代码的行为就像编译器在未应用优化的情况下翻译您的代码一样。除了少数例外,通常不能保证优化。要确保,我只会依靠在现实情况下查看编译器输出。
class
定义内部定义的方法会被隐式标记为inline
,这是自 C++98 以来的规定。如果你愿意,你可以将其显式声明,但这并不会有任何改变。这与在子类中使用virtual
类似,你可以将其显式声明,但这并不会改变任何东西。 - Slavainline
的实际现代含义并不是“提示优化器”,而是“此函数可以在多个翻译单元中定义,并且将始终在使用它的翻译单元中定义”。由头文件定义的函数应该是inline
,因为它们可能会被多次包含,另一部分告诉编译器它不一定需要为链接器单独生成定义,因为如果它总是选择内联它,定义将始终可见。 - ascheplerinline
。仅仅声明是不够的。正如上面所指出的,编译器可能有其他计划。请参考仿佛规则:如果你无法察觉到任何差别,编译器可以对代码进行任何它想要的更改。 - user4581301