2017-04-05 261 views
0

當在C++中的循環內聲明變量時,C++是否會在循環的每次迭代中重新創建變量?我的意思是,它是否爲另一個num變量重新分配內存?所以如果循環迭代5次,你會得到5個獨立的num變量與他們自己的唯一值嗎?在循環開始之前聲明一個變量是否是一種更好的做法,即使該變量只能在循環中使用?例如,如果我想將該變量用作計數器或佔位符?C++是否會重新創建循環中定義的變量?

// is this better code? 
// int num; 
for (int i = 0; i < 5; i++) { 
    int num; 
    // do stuff with num 
} 

回答

4

是的,如果num是內循環定義,那麼它會在每次循環運行時間代表不同的變量。每次控制通過它的定義時,它都會被重新初始化(如果有的話),並且每次迭代結束時,它都會被銷燬。

變量通常應該在可能的最窄範圍內聲明。所以如果num不需要從一次迭代到下一次迭代保留它的值,它通常應該在循環內部定義。如果它確實需要從一次迭代到下一次迭代保持它的值,那麼它必須在循環之外定義。

此風格最佳實踐有一些例外情況,例如初始化成本高昂時。

4

編譯器可能優化內存使用情況,因此變量只在物理上分配一次,然後在每次循環迭代中重用。但是,一般而言,範圍規則要求每個循環迭代對變量的不同實例進行操作。在類型複雜的情況下,比如類/結構體,這意味着在每次循環迭代時調用變量的構造函數和析構函數。

0

在你所描述的情況下,C++標準指定了變量的新實例在循環開始時被構造,並在循環結束時被銷燬。

究竟發生了什麼,當你想到它的本質時,除了重點之外。只要可觀察結果符合C++標準的規定,C++實現就可以以任何想要的方式實現它。

在這裏,你只是一個普通的花園品種int。正如我所描述的那樣,雖然它被正式構建並銷燬,但當變量被構建和銷燬時,沒有任何物質真的發生。 C++不需要在本地範圍內新構建的int被初始化爲任何特定值。因此,在這種情況下,典型的C++實現將簡單地將這個int分配給內存中的某個內存中的某個地方,並將其用於每個循環迭代。但是,如果你用一個更加充實的對象,用一個正式的構造函數替換這個int,你將會看到,在每次循環迭代開始時,對象的構造函數將被乖乖地調用,並且對象的析構函數將會是在循環迭代結束時(或執行線程離開循環的作用域時)乖乖地調用。

2

這是一個新變量。

for (int i = 0; i < 5; i++) { 
    const int num = i; 
    // do stuff with num 
} 

如果它真的是相同的變量,我們如何分配給一個常變量新的東西:你可以很容易的事實,這個編譯說服自己的是什麼?

至於它是否更有效率,你應該記住C++有一個非常好的優化編譯器。沒有真正的「成本」與堆棧變量相關聯。一個簡單的整數賦值顯然沒有任何副作用,因此編譯器重用相同的空間是微不足道的。如果你不需要循環外的變量,最好在循環中聲明它。

我建議使用https://gcc.godbolt.org/來查看爲幾個小函數生成的程序集,這些程序可以進行優化或不進行優化,它會讓您感覺到編譯器可以輕鬆優化。