昨天在一個(gè)論壇里看到一個(gè)帖子,是關(guān)于無(wú)限循環(huán)的選擇問題,之前也看到過很多次說(shuō)空f(shuō)or比while(1)效率高的論述,只是之前一直沒有功夫去考證。
話不多說(shuō),直入正題。
/*
*\brief 示例一:空f(shuō)or
*/
int main()
{
for(;;)
{}
return 0;
}
/*
*\brief 示例二:while(1)
*/
int main()
{
while(1)
{}
return 0;
}
借用曾經(jīng)看到的某論壇大師逢帖必發(fā)的一句話“不要迷信語(yǔ)言,要迷信編譯器”,撇去我對(duì)此人的偏見,對(duì)于這句話我還是比較認(rèn)同的,畢竟自己寫的代碼最終是由你用的編譯器來(lái)編譯并連接成的,語(yǔ)言只是你和它打交道的中介,至于最終怎么解釋執(zhí)行,完全是它有最終解釋權(quán)。
有點(diǎn)偏題,直接上編譯器生成的匯編碼(注,此處編譯器及版本為:g++ (GCC) 4.4.6 20120305)
400554: 55 push %rbp
400555: 48 89 e5 mov %rsp,%rbp
400558: eb fe jmp 400558 <main+0x4>
40055a: 90 nop
40055b: 90 nop
40055c: 90 nop
40055d: 90 nop
40055e: 90 nop
40055f: 90 nop
兩者生成的匯編代碼一致,就不多貼一份了。
事實(shí)證明,兩種無(wú)限循環(huán)寫法最終運(yùn)行效率一樣,但是為什么這么多人說(shuō)空f(shuō)or要比while(1)效率高呢?這其中還不乏一些很大的知名開源團(tuán)隊(duì)。出于科學(xué)求證的態(tài)度我又測(cè)試了老的GCC版本(g++ (GCC) 3.2.4),證明和上面大體是一樣的。但是當(dāng)我用VS2010和VC6.0測(cè)試時(shí)區(qū)別就出來(lái)了。
結(jié)果如下:
for(;;) 的反匯編:
int main()
{
00411350 push ebp
00411351 mov ebp,esp
00411353 sub esp,0C0h
00411359 push ebx
0041135A push esi
0041135B push edi
0041135C lea edi,[ebp-0C0h]
00411362 mov ecx,30h
00411367 mov eax,0CCCCCCCCh
0041136C rep stos dword ptr es:[edi]
for(;;)
{
}
0041136E jmp main+1Eh (41136Eh)
return 0;
00411370 xor eax,eax
}
while(1)的反匯編:
int main()
{
00411350 push ebp
00411351 mov ebp,esp
00411353 sub esp,0C0h
00411359 push ebx
0041135A push esi
0041135B push edi
0041135C lea edi,[ebp-0C0h]
00411362 mov ecx,30h
00411367 mov eax,0CCCCCCCCh
0041136C rep stos dword ptr es:[edi]
while(1)
0041136E mov eax,1
00411373 test eax,eax
00411375 je main+29h (411379h)
{
}
00411377 jmp main+1Eh (41136Eh)
return 0;
00411379 xor eax,eax
}
顯而易見,VS平臺(tái)下for(;;)生成的匯編指令少,并且不占用寄存器,沒有多余的判斷和跳轉(zhuǎn),比while (1)性能要好。
其實(shí)這種平臺(tái)相關(guān)的代碼之前我也在一篇博文中說(shuō)過(見:
編譯器背后的小故事),
C++標(biāo)準(zhǔn)僅僅是一些規(guī)則,而編譯器才是最終規(guī)則的實(shí)現(xiàn)者,對(duì)于很多細(xì)節(jié)規(guī)則并沒有限定,這也要求我們盡量明確寫出與編譯器實(shí)現(xiàn)差異無(wú)關(guān)的代碼,就如char的實(shí)現(xiàn)是按照signed還是unsigned等等,這些標(biāo)準(zhǔn)沒有具體說(shuō)明,各個(gè)編譯器廠商自然會(huì)有各自的實(shí)現(xiàn)方法,很多時(shí)候我們?cè)谝粋€(gè)平臺(tái)習(xí)慣的東西,換到另一個(gè)平臺(tái)就不一定湊效,這時(shí)候就需要我們知道編譯器具體實(shí)現(xiàn)的過程,或者只需要看一下實(shí)現(xiàn)的結(jié)果。
正如那句“不存在沒有bug的程序,只存在暫時(shí)未發(fā)現(xiàn)bug的程序”一樣,程序員的世界里,“沒有最好,只有更好” 也是至理名言 ---peakflys