我喜欢使用const& type T = LongVariableName
重新标记一小段代码中的变量,尤其是涉及公式的变量。
例如:
const double& x = VectorNorm;
double y = a*x*x*x + b*x*x + c*x + d;
我认为编译器应该足够智能,以优化这些参考变量。这几乎总会发生吗?什么时候不行?
答案 0 :(得分:0)
由您设置的编译器和优化选项决定 - 无法保证它将被优化或不被优化。启用优化的现代编译器可能会优化它,但更好的问题是:你应该关心吗?除非你处于每秒运行数千次的紧密循环中,否则不要担心。代码清晰度通常比削减几个时钟周期更重要。
但无论如何,让我们来看看。我通过MinGW使用gcc 4.7.2。我们将使用此代码:
so.cpp:
#include <cstdio>
int main()
{
float aReallyLongNameForAVariable = 4.2;
#ifdef SHORT_REF
const float& x = aReallyLongNameForAVariable;
float bar = x * x * x;
#else
float bar = aReallyLongNameForAVariable * aReallyLongNameForAVariable * aReallyLongNameForAVariable;
#endif
printf("bar is %f\n", bar);
return 0;
}
没有“速记参考”,我们得到以下程序集:
g++ -S -masm=intel -o noref.S so.cpp
call ___main
mov eax, DWORD PTR LC0
mov DWORD PTR [esp+28], eax
fld DWORD PTR [esp+28]
fmul DWORD PTR [esp+28]
fmul DWORD PTR [esp+28]
fstp DWORD PTR [esp+24]
fld DWORD PTR [esp+24]
fstp QWORD PTR [esp+4]
mov DWORD PTR [esp], OFFSET FLAT:LC1
call _printf
mov eax, 0
leave
现在让我们使用参考:
g++ -DSHORT_REF -S -masm=intel -o ref.S so.cpp
call ___main
mov eax, DWORD PTR LC0
mov DWORD PTR [esp+20], eax
lea eax, [esp+20]
mov DWORD PTR [esp+28], eax
mov eax, DWORD PTR [esp+28]
fld DWORD PTR [eax]
mov eax, DWORD PTR [esp+28]
fld DWORD PTR [eax]
fmulp st(1), st
mov eax, DWORD PTR [esp+28]
fld DWORD PTR [eax]
fmulp st(1), st
fstp DWORD PTR [esp+24]
fld DWORD PTR [esp+24]
fstp QWORD PTR [esp+4]
mov DWORD PTR [esp], OFFSET FLAT:LC1
call _printf
mov eax, 0
leave
所以这是一个更多的集会。但是当我们启用优化时会发生什么?
g++ -DSHORT_REF -O2 -S -masm=intel -o ref.S so.cpp
g++ -O2 -S -masm=intel -o noref.S so.cpp
两者都生成相同的程序集:
call ___main
fld DWORD PTR LC0
fstp QWORD PTR [esp+4]
mov DWORD PTR [esp], OFFSET FLAT:LC1
call _printf
xor eax, eax
leave
所以你有它。现代编译器(至少是gcc)优化了参考。