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

S.H*_*S.H -5 c++ performance for-loop

问题说明了一切:是

for( int k = 5; k--;)
Run Code Online (Sandbox Code Playgroud)

比...快

for( int k = 4; k > -1; --k)
Run Code Online (Sandbox Code Playgroud)

为什么?

编辑: 我在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:
Run Code Online (Sandbox Code Playgroud)

发布:

; 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
Run Code Online (Sandbox Code Playgroud)

Ton*_*roy 6

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

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

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