簡體   English   中英

"C++ 在 for 循環中聲明 int"

[英]C++ Declaring int in the for loop

好久沒用C++了。 我一直依靠我的 Java 編譯器來進行優化。

在 C++ 中執行 for 循環的最優化方法是什么? 或者現代編譯器現在都一樣了嗎? 在“舊時代”,情況有所不同。

for (int i=1; i<=100; i++)

我會說像這樣的微不足道的東西可能是由編譯器優化的,你不應該擔心它們。 第一個選項是最易讀的,所以你應該使用它。

編輯:添加其他答案所說的,還有不同之處在於,如果在循環初始化程序中聲明變量,它將在循環結束后停止存在。

差異在於范圍。

for(int i = 1; i <= 100; ++i)

通常是優選的,因為那時i的范圍僅限於for循環。 如果在for循環之前聲明它,那么它在for循環結束后繼續存在並且可能與其他變量沖突。 如果你只是在for循環中使用它,那么就沒有理由讓它存在的時間長於那個。

讓我們說原始海報有一個他們真正想要優化的循環 - 每個指令都被計算在內。 我們怎樣才能 - 憑經驗 - 弄清楚他的問題的答案?

gcc至少有一個有用的,如果不常用的開關,'-S'。 它轉儲.c文件的匯編代碼版本,可用於回答OP姿勢等問題。 我寫了一個簡單的程序:

int main( )
{
    int sum = 0;

    for(int i=1;i<=10;++i)
    {
        sum = sum + i;
    }
    return sum;
}

並運行: gcc -O0 -std=c99 -S main.c ,創建主程序的匯編版本。 這是main.s的內容(刪除了一些絨毛):

    movl    $0, -8(%rbp)
    movl    $1, -4(%rbp)
    jmp     .L2
.L3:
    movl    -4(%rbp), %eax
    addl    %eax, -8(%rbp)
    addl    $1, -4(%rbp)
.L2:
    cmpl    $10, -4(%rbp)
    jle     .L3

你不需要成為裝配專家來弄清楚發生了什么。 movl移動值,addl添加東西,cmpl比較和jle代表'jump if than',$是常量。 它將0加載到某個東西 - 必須是'sum',1加入其他東西 - 啊,'我'! 跳轉到L2我們比較10,跳轉到L3進行添加。 再次進入L2進行比較。 整齊! 一個for循環。

將程序更改為:

int main( )
{
    int sum = 0;
    int i=1;
    for( ;i<=10;++i)
    {
        sum = sum + i;
    }
    return sum;
}

重新運行gcc和由此產生的組件將非常相似。 有一些東西正在記錄行號,所以它們不會完全相同,但程序集最終是相同的。 與最后一個案例相同的結果。 因此,即使沒有優化,代碼也差不多。

為了好玩,請使用'-O3'而不是'-O0'重新運行gcc以啟用優化並查看.s文件。

main:
movl    $55, %eax
ret

gcc不僅弄清楚我們正在做一個for循環,而且還意識到它在編譯時為我們循環運行了一段時間,清除了'i'和'sum'並硬編碼了答案 - 55 ! 這很快 - 盡管有點做作。

故事的道德啟示? 花時間確保您的代碼干凈且設計精良。 可讀性和可維護性代碼。 生活在山露和cheetos上的人比我們更聰明,並為我們處理了大部分這些簡單的優化問題。 玩得開心!

一樣的。 編譯器會將這些優化為同樣的東西。

即使它們不相同,與循環的實際主體相比的差異也可以忽略不計。 你不應該擔心像這樣的微優化。 除非你進行性能分析以確定它是否真的有所作為,否則你不應該進行微觀優化。

速度方面也是如此。 如果您以后沒有使用i,編譯器將進行優化。

在風格方面 - 我將定義放在循環結構中,因為它可以降低您在以后定義另一個時會發生沖突的風險。

不要擔心微優化,讓編譯器去做。 選擇最具可讀性的。 請注意,在for initial語句中聲明變量會將變量范圍限定for語句(C ++ 03§6.5.31 ),盡管編譯器的確切行為可能會有所不同(有些for您選擇)。 如果循環外的代碼使用變量,則在循環外聲明它。 如果變量對循環是真正的本地變量,則在初始化程序中聲明它。

已經提到兩者之間的主要區別在於范圍。 確保您了解編譯器如何處理聲明為的int的范圍

for (int i = 1; ...;...)

我知道當使用MSVC ++ 6時,我仍然在循環之外的范圍內,就像它在循環之前聲明一樣。 這種行為與VS2005不同,我必須檢查,但我認為我使用的最后一個版本的gcc。 在這兩個編譯器中,該變量僅在循環內的范圍內。

for(int i = 1; i <= 100; ++i)

這是最容易閱讀的,但ANSI C / C89除外,它是無效的。

C++ for 循環實際上是一個打包的 while 循環。

   for (int i=1; i<=100; i++){
   some foobar ; }

與編譯器完全相同。

{ int i=1 ;
while (i<=100){
some foobar ;
i++ ; }
}

這都一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM