2010-01-29 219 views
11

比方說,我有這樣的程序:靜態變量

class Foo { 
public: 
    unsigned int bar() { 
     static unsigned int counter = 0; 
     return counter++; 
    } 
}; 

int main() 
{ 
    Foo a; 
    Foo b; 
} 

(當然,這個例子是沒有意義的,因爲我明明申報「計數器」作爲私人屬性,但它只是爲了說明問題)。

我想知道C++的行爲在這種情況:將在欄()方法變量「計數器」是每一個實例一樣嗎?

回答

10

是的,counter將在可執行文件中的Foo類型的所有對象實例之間共享。只要你處於一個單線程環境中,它就可以像預期的那樣作爲共享計數器工作。

在多線程環境中,你將有有趣的比賽條件來調試:)。

+0

+1在多線程環境中提到危險。 – Omnifarious 2010-01-29 18:20:51

+0

假設編譯器尚未爲您處理該問題。語言定義是變量在所有方法調用中保持一致。因此,編譯器的工作是強制執行的,所以在多線程語言(C++的下一個版本)中,它是編譯器的工作。在這個版本中,它依賴於編譯器與線程庫的集成。 gcc已經涵蓋了這一點,保證在多個線程中對靜態變量的訪問是安全的。 – 2010-01-29 18:24:58

+0

@Martin York:即C++ 0x中的靜態變量保證爲線程本地?有趣的是,它可能會讓一些人大吃一驚。就像一個很好的靜態類實例計數器。突然間,你會計算每個線程的實例。我無法相信他們會做出這樣的改變。你確定?! – Omnifarious 2010-01-29 18:27:54

2

通過「是每一個實例相同的」你的意思是會有這個變量在每個類實例共享的一個實例,那麼是的,這是正確的。該類的所有實例都將使用同一個變量實例。

但請記住,與類變量,你必須拿東西一樣多線程考慮在許多情況下,這是一個完全不同的話題。

1

的C++程序設計語言(第2版),200頁,由Bjarne Stroustrup的:

不要使用靜態除了內部[平原]函數(§7.1.2)和類(§10.2.4)。

+4

規則是太棒了。只有在正確的上下文中使用__BUT__。一個低級的用戶可能會把這個報價拿給哈特。如果你想引用這樣的話,你必須包含完整的上下文。 – 2010-01-29 18:30:23

0

你只需要把握兩點:

  1. 靜態變量存儲在執行程序(這是作爲全局變量的相同)的靜態區域。
  2. 範圍由parentheses.Additionally靜態變量的一般規則限定具有內部鏈接。
+0

終身不是該計劃的生命。它是從第一次使用(可能永遠不會)直到銷燬(這是創建靜態變量的相反順序)。阿洛斯注意初始化是好的,因爲它是功能的一部分,而不是類。 – 2010-01-29 18:28:47

+0

@niel ..我的壞!我沒有看到 – sud03r 2010-01-29 18:43:10

+0

最後一句是關於命名空間範圍的靜態變量。本地靜態變量(如問題中的那些變量)沒有鏈接。 (沒有辦法從不同的作用域引用局部變量,例如,如何引用main中定義的變量?'main():: v'不起作用)。 – 2010-01-29 19:34:43

1

你的例子是一對夫婦線遠離被一些你可以編譯和測試:

#include <iostream> 
using namespace std; 
class Foo { 
public: 
    unsigned int bar() { 
     static unsigned int counter = 0; 
     return counter++; 
    } 
}; 

int main() 
{ 
    Foo a; 
    Foo b; 

    for (int i=0; i < 10; i++) 
     cout<<i<<". "<<a.bar()<<"/"<<b.bar()<<endl; 
} 

輸出看起來是這樣的:

0. 1/0 
1. 3/2 
2. 5/4 
3. 7/6 
4. 9/8 
5. 11/10 
6. 13/12 
7. 15/14 
8. 17/16 
9. 19/18 

所以,是的,櫃檯跨共享所有實例。

+0

有趣的是,你的輸出是序列點和執行順序如何工作的完美例子,並可能導致違反直覺的結果。 – Omnifarious 2010-01-29 20:18:51