问题说明了一切:
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
答案 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
)并查看它是否有所不同。确保在测试之前启用优化!