空的“别的”会随时消耗

时间:2013-12-02 11:56:06

标签: c++

的计算成本是否有任何差异
if(something){
    return something;
}else{
    return somethingElse;
}

if(something){
    return something;
}
//else (put in comments for readibility purposes)
return somethingElse;

理论上我们有命令(其他),但它似乎不应该产生实际差异。

编辑: 运行不同设置大小的代码后,我发现实际上存在差异,没有其他代码似乎效率提高了1.5%。但它很可能取决于编译器,正如下面许多人所说的那样。我在代码上测试了它:

int withoutElse(bool a){
if(a)
    return 0;
return 1;

}


int withElse(bool a){
if(a)
    return 0;
else
    return 1;
}


int main(){
using namespace std;
bool a=true;
clock_t begin,end;
begin= clock();
for(__int64 i=0;i<1000000000;i++){
    a=!a;
    withElse(a);
}
end = clock();
cout<<end-begin<<endl;

begin= clock();
for(__int64 i=0;i<1000000000;i++){
    a=!a;
    withoutElse(a);
}
end = clock();
cout<<end-begin<<endl;

return 0;
}

检查从1 000 000到1 000 000 000的循环,结果始终不同

编辑2: 汇编代码(再一次,使用Visual Studio 2010生成)也显示出很小的差异(显然,我对汇编程序不好:()

   ?withElse@@YAH_N@Z PROC                  ; withElse, COMDAT
   ; Line 12
push    ebp
mov ebp, esp
sub esp, 192                ; 000000c0H
push    ebx
push    esi
push    edi
lea edi, DWORD PTR [ebp-192]
mov ecx, 48                 ; 00000030H
mov eax, -858993460             ; ccccccccH
rep stosd
   ; Line 13
movzx   eax, BYTE PTR _a$[ebp]
test    eax, eax
je  SHORT $LN2@withElse
   ; Line 14
xor eax, eax
jmp SHORT $LN3@withElse
   ; Line 15
jmp SHORT $LN3@withElse
   $LN2@withElse:
   ; Line 16
mov eax, 1
   $LN3@withElse:
   ; Line 17
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
   ?withElse@@YAH_N@Z ENDP                  ; withElse

   ?withoutElse@@YAH_N@Z PROC               ; withoutElse, COMDAT
   ; Line 4
push    ebp
mov ebp, esp
sub esp, 192                ; 000000c0H
push    ebx
push    esi
push    edi
lea edi, DWORD PTR [ebp-192]
mov ecx, 48                 ; 00000030H
mov eax, -858993460             ; ccccccccH
rep stosd
   ; Line 5
movzx   eax, BYTE PTR _a$[ebp]
test    eax, eax
je  SHORT $LN1@withoutEls
   ; Line 6
xor eax, eax
jmp SHORT $LN2@withoutEls
   $LN1@withoutEls:
   ; Line 7
mov eax, 1
   $LN2@withoutEls:
   ; Line 9
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
   ?withoutElse@@YAH_N@Z ENDP               ; withoutElse

2 个答案:

答案 0 :(得分:4)

它通常是不同的,但编译器可能决定在两种情况下都执行相同的跳转(它实际上总是这样做)。 查看编译器执行操作的最佳方法是读取汇编程序。假设您正在使用gcc,可以尝试使用

gcc -g -c -fverbose-asm myfile.c; objdump -d -M intel -S myfile.o > myfile.s

创建了汇编程序/ c代码的混合,并使工作在开始时更容易。

至于你的例子:

<强> CASE1

if(something){
23: 83 7d fc 00             cmp    DWORD PTR [ebp-0x4],0x0
27: 74 05                   je     2e <main+0x19>
    return something;
29: 8b 45 fc                mov    eax,DWORD PTR [ebp-0x4]
2c: eb 05                   jmp    33 <main+0x1e>
}else{
    return 0;
2e: b8 00 00 00 00          mov    eax,0x0
}

<强> CASE2

if(something){
23: 83 7d fc 00             cmp    DWORD PTR [ebp-0x4],0x0
27: 74 05                   je     2e <main+0x19>
    return something;
29: 8b 45 fc                mov    eax,DWORD PTR [ebp-0x4]
2c: eb 05                   jmp    33 <main+0x1e>
return 0;
2e: b8 00 00 00 00          mov    eax,0x0

您可以想象 没有差异

答案 1 :(得分:2)

如果输入`return,它将无法编译 认为一旦代码被编译,所有ifs,elses和循环都被改为goto的

If (cond) { code A } code B

转向

if cond is false jump to code b
code A
code B

和     如果(cond){code A} else {code B} code C

转向

if cond is false jump to code B
code A
ALWAYS jump to code C
code B

code C

大多数处理器在检查它们是否实际跳跃之前“猜测”它们是否会跳跃。根据处理器的不同,它可能会影响性能,从而无法猜测。

所以答案是肯定的! (除非在第一次比较结束时总是跳跃)进行ALWAYS跳跃需要2-3个周期,而不是在第一个if中。