C++中迴圈開銷,你瞭解多少?快隨我一起進來看看吧

由於每條 C++ 語句都只會進行幾次記憶體訪問,通常情況下熱點程式碼都不會是一條單獨的語句,除非受其他因素的作用,讓其頻繁地執行。這些因素之一就是該語句出現在了迴圈中。這樣,合計開銷就是該語句的開銷乘以該語句被執行的次數了。

C++中迴圈開銷,你瞭解多少?快隨我一起進來看看吧

如果你很幸運,可能會偶然找到這樣的程式碼。分析器可能會指出一條單獨的語句被執行了 100 萬次,或者其他的熱點函式包含以下這樣的迴圈:

for (int i=1; i<1000000; ++i) { do_something_expensive(); if (mostly_true) { do_more_stuff(); even_more(); } }

這個迴圈中的語句很明顯會被執行 100 萬次,因此它是熱點語句。看起來你需要花點精力去最佳化。

當一個迴圈被巢狀在另一個迴圈裡面的時候,程式碼塊的迴圈次數是內層迴圈的次數乘以外層迴圈的次數。例如:

for (int i=0; i<100; ++i) { for (int j=0; j<50; ++j) { fiddle(a[i][j]); } }

在這裡,程式碼塊的迴圈次數是 100*50=5000。

C++中迴圈開銷,你瞭解多少?快隨我一起進來看看吧

上面的程式碼塊非常直接。但是實際上這裡可能有無數種變化。例如,當進行數學運算時,在有些重要的情況下會對三角矩陣進行迴圈計算。而且有時候,程式碼編寫得非常糟糕,需要花費很大氣力才能看清巢狀迴圈的輪廓。

巢狀迴圈可能並非一眼就能看出來。如果一個迴圈呼叫了一個函式,而這個函式中又包含了另外一個迴圈,那麼內層迴圈就是巢狀迴圈。正如我們稍後會在 7。1。8 節中看到的,有時在外層迴圈中重複地呼叫函式的開銷也是可以消除的。

C++中迴圈開銷,你瞭解多少?快隨我一起進來看看吧

記憶體迴圈可能被嵌入在標準庫函式中,特別是處理字串或字元的 I/O 函式。如果這些函式被重複呼叫的次數非常多,那麼可能值得去重新實現標準函式庫中的函式來回避呼叫開銷。

評估迴圈次數為變數的迴圈的開銷

不是所有迴圈中的迴圈次數都是很明確的。許多迴圈處理會不斷重複直至滿足某個條件為止,比如有些迴圈會重複地處理字元,直至找到空格為止;還有些迴圈則會重複地處理數字,直到遇到非數字為止。這種迴圈的重複次數也是可以估算出來的。

當然,只需要大致地估算一下即可,例如每個數字的平均位數是 5,或是每個單詞的平均字母數是 6。估算的目的是找出可能需要最佳化的程式碼。

C++中迴圈開銷,你瞭解多少?快隨我一起進來看看吧

識別出隱式迴圈

響應事件的程式(例如 Windows UI 程式)在最外層都會有一個隱式迴圈。這個迴圈甚至在程式中是看不到的,因為它被隱藏在了框架中。如果這個框架以最大速率接收事件的話,那麼每當事件處理器取得程式控制權,或是在事件分發前,抑或是在事件分發過程中都會被執行的程式碼,以及最頻繁地被分發的事件中的程式碼都可能是熱點程式碼。

識別假迴圈

不是所有的 while 或者 do 語句都是迴圈語句。我就曾經遇到過使用 do 語句幫助控制流程的程式碼。下面這段示例程式碼還有更好的實現方式,不過使用了更復雜的 if-then-else 邏輯的話,這種慣用法就有其用武之地了。下面這個“迴圈”只會被執行一次。當它遇到 while(0) 後就會退出:

do { if (!operation1()) break; if (!operation2(x,y,z)) break; } while(0);

這種慣用法也時常被用於將幾條語句“打包”為 C 風格的宏。

C++中迴圈開銷,你瞭解多少?快隨我一起進來看看吧

C++ 語句的出現會迴圈使用,但也不是全部的語句都會迴圈使用,合計開銷就是該語句的開銷乘以該語句被執行的次數了。看完這篇文章,相信你對於c++的開銷迴圈使用會有所瞭解,趕快和身邊的朋友一起分享吧。