2010-01-29 217 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