2010-11-11 111 views
5

好的,我想知道爲什麼這段代碼正在工作,我只是意識到我在同一範圍內有兩個具有相同名稱的變量。爲什麼這個C++工作? (具有相同名稱的變量)

我使用g ++(gcc 4.4)。

for(int k = 0 ; k < n ; k++) 
    { 
     while(true) 
     { 
      i = Tools::randomInt(0, n); 
      bool exists = false; 

      for(int k = 0 ; k < p_new_solution_size ; k++) 
       if(i == p_new_solution[k]) 
       { 
        exists = true; 
        break; 
       } 
      if(!exists) 
       break; 
     } 

     p_new_solution[p_new_solution_size] = i; 
     p_new_solution_size++; 
    } 
+1

試着打開'-Wall',它可能會抱怨更多? – 2010-11-11 03:48:05

+1

'我在同一範圍內有兩個相同名稱的變量'哪裏? – 2013-05-03 15:45:13

回答

4

好吧,我想知道爲什麼這個代碼工作,我只是意識到我在同一範圍內有兩個同名的變量。

你對範圍似乎很困惑。它們不在「範圍內」... for循環的k有自己的嵌套/內部範圍。更重要的是,明白爲什麼語言允許的話,考慮:

#define DO_SOMETHING \ 
    do { for (int i = 1; i <= 2; ++i) std::cout << i << '\n'; } while (false) 

void f() 
{ 
    for (int i = 1; i <= 10; ++i) 
     DO_SOMETHING(); 
} 

這裏,由宏「DO_SOMETHING」取代文本在同一範圍內,我被評估。如果您正在編寫DO_SOMETHING,您可能需要將其擴展存儲到變量中,然後解決標識符i - 顯然,您無法知道它是否已存在於調用上下文中。你可以嘗試挑選一些比較模糊的東西,但是你會讓人們使用這些複雜的變量名稱來維護代碼的可靠性,無論遲早會有衝突。所以,語言只是讓內部作用域引入具有相同名稱的變量:直到其範圍退出時使用最內部的匹配。

即使你沒有處理宏,也不得不停下來想一想,一些外層作用域是否已經使用相同的名字。如果你知道你只是想快速操作,你可以在不考慮更大的上下文的情況下將它彈出一個獨立(嵌套)範圍(只要你沒有實際上想要使用外部變量的代碼:如果你這樣做那麼你有時可以明確地指定它(如果它是由命名空間和類範圍的,但是如果它在函數體中,你最終需要改變你自己的循環變量的名字(或者在引入你的同名命名之前創建一個引用或其他東西)變量))。

+0

好吧,我知道了,我的意思是......在經歷了這些年來的C++和編譯器之後,我從未想過這件事。我只是有一個小問題:所以DO_SOMETHING()是在一個不同的範圍內,但如果它不影響我的變量,它可以使用它的值,通過outter循環設置權?如果它不是一個宏而不是DO_SOMETHING(),那麼你有obj-> do_this()。您仍然可以更改範圍,但由於此方法不能使用較早的「i」值,還會發生什麼變化?我問這個知道什麼變化的名字,因爲我知道編譯器的工作方式..有一整年關於他們,我只是沒有知道這個工作在海灣合作委員會 – hfingler 2010-11-11 04:21:54

+0

@polar:正如你所說,如果DO_SOMETHING沒有影子外面我可以得到或設置它。有時候,這是有意的:例如,一個強大的方法來實現企業級質量的調試,其中有許多正交分類來協助過濾,這是通過具有範圍錯誤上下文來實現的。在該模型中,您有一個LOG宏,實際上它需要一個具有特定名稱的錯誤上下文變量。如果您想優化報告,您可以隱藏外部版本並修改一些分類 - 提供增量 - 但不需要重新指定每個LOG使用的所有內容。 – 2010-11-11 04:46:04

+0

如果DO_SOMETHING是一個函數而不是宏,那麼它不能訪問調用者範圍內的任何東西(不僅僅是函數,而且是DO_SOMETHING不是其成員的名稱空間/類範圍)。它仍然可以訪問它嵌套的作用域,這對於宏來說並不是這樣(宏不記得它們被定義在哪個名稱空間中)。 – 2010-11-11 04:49:57

9

在內部for循環陰影(或隱藏)在外部for循環kk的。

您可以在不同的作用域聲明多個具有相同名稱的變量。一個非常簡單的例子是以下幾點:

int main() 
{ 
    int a;  // 'a' refers to the int until it is shadowed or its block ends 
    { 
     float a; // 'a' refers to the float until the end of this block 
    }   // 'a' now refers to the int again 
} 
+0

編譯器是否應該發出警告,說明兩個變量在同一個作用域上具有相同的名稱?我的意思是......我可以在內部循環中使用外部'k',因此它們處於相同的範圍。 – hfingler 2010-11-11 03:50:46

+0

你不能,因爲它是陰影。 – Crashworks 2010-11-11 03:51:59

+0

@極地:它可能會發出警告,但不一定。有很多情況可能發生。例如,你可能在命名空間範圍有一個變量,或者你可能有一個類成員變量。 – 2010-11-11 03:52:43

1

因爲你被允許具有相同的範圍內的兩個同名的變量,但不是相同的聲明空間內。編譯器採用適當名稱的最本地變量,類似於如何用名稱X的成員變量「隱藏」名稱X的全局變量。儘管如此,您應該會收到警告。

+0

這並不意味着聽起來很黑,我真的好奇 - 爲了我自己的學習利益,有人可以向我解釋什麼是不正確的,會導致downvote?乾杯。 – dlanod 2010-11-11 04:19:35

+0

當我在那裏看到它時,我想到了同樣的事情。爲什麼有人會低估這個答案?僅僅因爲它很簡單卻可以理解? – hfingler 2010-11-11 04:27:15

+1

我沒有讓你失望,但你應該得到一些解釋,我會猜測。我懷疑這只是一個術語問題。這個想法是對的,但是你要麼分享要麼接受極地的想法,即兩個k在同一個範圍內。他們不是 - 他們在一個內部範圍內嵌套在一個外部範圍內。我不確定你對範圍與「聲明空間」的理解,但是我從來沒有聽說過空間(26年編程,大部分是C/C++)。 – 2010-11-11 04:54:06

0

在C/C++的變量範圍由括號有限,所以下面的代碼是有效的編譯器:

int k() 
{ 
    int k; 
    { 
     int k; 
     { 
      int k;    
     }  
    } 
} 
+1

你的意思是*分支*或*大括號*? – fredoverflow 2010-11-11 11:02:19

2

從標準文檔,二段3.3.1

每名是在程序文本的一些部分引入稱爲聲明性區域,這是最大的其中該名稱有效的 程序的一部分,也就是說,該名稱可以用作非限定名稱來指代同一個實體。一般而言,每個特定名稱僅在程序文本 的一些可能不連續的部分內有效,稱爲其範圍。爲了確定聲明的範圍,有時可以方便地參考聲明的潛在範圍 。聲明的範圍是相同,作爲其潛在範圍,除非潛在範圍包含另一個 聲明具有相同名稱。在這種情況下,內部(含有)聲明性區域 區域中的聲明的潛在範圍從外部(包含)聲明區域中的聲明範圍中排除。

它可能聽起來令人困惑,你的第一次閱讀,但它確實回答你的問題。

潛在作用域與聲明範圍相同,除非發生另一個(內部)聲明。如果發生,外部聲明的潛在範圍是刪除只是內部聲明是成立的。

希望清楚,它有幫助..

+0

你很清楚,但是這段文字需要一些時間才能完全忽略。但它肯定回答我的問題。謝謝。 – hfingler 2010-11-11 05:41:20

相關問題