2016-05-31 71 views
1

我有點在這種情況下困惑:變量名歧義C++

#include <iostream> 

void function(int origin) 
{ 
    if (origin < 0) 
    { 
     double origin = 0.3; 

     std::cout << origin << std::endl; 
    } 
} 

int main() 
{ 
    function(-4); 
} 

它被編譯併成功下V120工具集使用VS2013運行。是不是C++錯了?因爲做同樣的事情,但只是在函數的開始,它會產生編譯時錯誤。

+1

這不是問題,但不要使用'std :: endl',除非你需要額外的東西。 ''\ n''結束一行。 –

+1

@PeteBecker哇,來自上師的建議無法避免;)我從來沒有想過** :: endl **和**'\ n'**之間有一些區別。將通過一些關於它的參考。謝謝 –

回答

1

我不介意這種C++行爲。當然,它可能會導致錯誤/疏漏,正如你已經證明的那樣。但是,你可以在C爲此++

for (int i = 0; i < 4; ++i) { 
    for (int i = 0; i < 5; ++i) { 
     cout << i; 
    } 
    cout << i; 
} 
cout << endl; 
for (int i = 0; i < 4; ++i) { 
    for (int j = 0; j < 5; ++j) { 
     cout << j; 
    } 
    cout << i; 
} 

並且因爲i在內部for循環的範圍重新定義爲一個不同的變量的結果是相同的。

在其他語言如C#中你不能這樣做。它會告訴你試圖在內部範圍內重新聲明一個同名的變量。

我覺得這種過度保護。當我用循環剪切和粘貼代碼時,必須重新聲明i(我們都傾向於將其用作循環變量)爲i1i2等等,我總是會錯過一個,使用剪切和粘貼代碼,所以我在i3循環中使用arr[i],當時我的意思是arr[i3](哎呦)。

在生產代碼中,我同意防禦性編碼意味着您應該在同一個函數中爲循環變量使用不同的名稱。

但是在試驗時能夠在嵌套for循環中重用變量名是很好的。 C++給你這個選擇。

1

是不是C++錯了?

不需要。重新聲明標識符是完全合法的,只要它在不同的範圍內即可。在這種情況下,範圍是if語句的當時主體。

它並不含糊。將使用最近的前面的聲明。

+1

雖然它是有效的,但它通常不被推薦,因爲它可能導致錯誤。 – SurvivalMachine

1

不,這沒有錯。根據標準,這是完全有效的行爲。

void function(int origin) 
{ 
    if (origin < 0) // scope of the first 'origin' 
    { 
     double origin = 0.3; // scope of the second 'origin' begins 
          // scope of the first 'origin' is interrupted 

     std::cout << origin << std::endl; 
    } //block ends, scope of the second 'origin' ends 
     //scope of the first 'origin' resumes 
} 

由於tupe_cat表示,如果它們的作用域變化,重新聲明它總是有效的。在這種情況下,屬於內部範圍的變量將超出外部範圍。

2

這根據C++標準是合法的,節3.3.3.1:

在一個塊中聲明的名稱是局部的塊;它有塊範圍。它的潛在範圍從宣佈的角度開始,到結束時結束。在塊範圍聲明的變量是局部變量。

這樣的重新聲明隱藏了origin參數。

原因做同樣的事情,但只是在函數的開始它會給編譯時錯誤。

你得到一個錯誤,因爲C++標準明確禁止這樣的重複宣告第3.3.3.2:

的參數名稱,不得在函數定義的最外層塊,也不在最外層塊中重新聲明任何與函數嘗試塊關聯的處理程序。

這種排除的原因是函數參數對函數的外部範圍是局部的,所以如果重新聲明沒有另一個大括號,會在同一範圍內引入重複標識符。