" for(int k = 5; k - ;)"对于(int k = 4; k> -1; - k)"快于"

时间:2014-10-22 08:06:28

标签: c++ performance for-loop

问题说明了一切:

for( int k = 5; k--;)

for( int k = 4; k > -1; --k)

为什么?

修改 我在MSVC2012中生成了用于调试和发布的程序集。但是(这是我第一次分析汇编代码),我真的无法理解它。我alredy添加了“std :: cout”以防止编译器在发布优化期间删除这两个循环。 有人能帮我解决装配意味着什么吗?

调试:

; 10   :    for( int k = 5; k--;){ std::cout << k; }

    mov DWORD PTR _k$2[ebp], 5
$LN5@wmain:
    mov eax, DWORD PTR _k$2[ebp]
    mov DWORD PTR tv65[ebp], eax
    mov ecx, DWORD PTR _k$2[ebp]
    sub ecx, 1
    mov DWORD PTR _k$2[ebp], ecx
    cmp DWORD PTR tv65[ebp], 0
    je  SHORT $LN4@wmain
    mov esi, esp
    mov eax, DWORD PTR _k$2[ebp]
    push    eax
    mov ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
    call    DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
    cmp esi, esp
    call    __RTC_CheckEsp
    jmp SHORT $LN5@wmain
$LN4@wmain:

; 11   : 
; 12   :    for( int k = 4; k > -1; --k){ std::cout << k; }

    mov DWORD PTR _k$1[ebp], 4
    jmp SHORT $LN3@wmain
$LN2@wmain:
    mov eax, DWORD PTR _k$1[ebp]
    sub eax, 1
    mov DWORD PTR _k$1[ebp], eax
$LN3@wmain:
    cmp DWORD PTR _k$1[ebp], -1
    jle SHORT $LN6@wmain
    mov esi, esp
    mov eax, DWORD PTR _k$1[ebp]
    push    eax
    mov ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
    call    DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
    cmp esi, esp
    call    __RTC_CheckEsp
    jmp SHORT $LN2@wmain
$LN6@wmain:

推出:

; 10   :    for( int k = 5; k--;){ std::cout << k; }

    mov esi, 5
$LL5@wmain:
    mov ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
    dec esi
    push    esi
    call    DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
    test    esi, esi
    jne SHORT $LL5@wmain

; 11   : 
; 12   :    for( int k = 4; k > -1; --k){ std::cout << k; }

    mov esi, 4
    npad    3
$LL3@wmain:
    mov ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
    push    esi
    call    DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
    dec esi
    cmp esi, -1
    jg  SHORT $LL3@wmain

3 个答案:

答案 0 :(得分:6)

[ UPDATE 问题已更新,因此不再有所不同] 他们做了不同的事情......第一个执行k值4的循环到0 ,而第二个循环从5减少到1 ......如果循环体确实与数字的大小有关,那么它们的性能可能不同。

忽略这一点,在大多数CPU上k--偶然设置&#34;标志&#34;寄存器通常称为&#34;零&#34; flag,因此在决定是否退出之前不需要进一步的显式比较。仍然, 一个优化者应该意识到这一点并避免任何不必要的第二次比较,即使是第二个循环

通用的讽刺:编译器可以做很多事情,标准当然也没有说明这两种实现的相对性能,所以最终唯一的方法就是知道 - 如果你有理由关心 - 是使用您想要生产的相同编译器和命令行选项,然后仔细检查生成的程序集或机器代码和/或测量非常。当可执行文件部署在不同的硬件上,编译器与更高版本的编译器,不同的标志,不同的编译器等时,结果可能会有所不同。

答案 1 :(得分:1)

小心,两个循环不等同:

for( int k = 5; k--;) cout << k << endl;

打印 4 3 2 1 0 。而

for( int k = 5; k > 0; k--) cout << k << endl;

打印 5 4 3 2 1

从性能的角度来看,您可以对编译器有足够的信心。在大多数情况下,现代编译器知道如何比我们更好地优化它。

答案 2 :(得分:-1)

这取决于你的编译器。可能不会,但一如既往,必须要确定一下。或者您可以查看生成的汇编代码(例如gcc -S)并查看它是否有所不同。确保在测试之前启用优化!