C++ 实例方法中的静态变量
假设我有一个程序:C++ 实例方法中的静态变量,c++,static-variables,instance-methods,C++,Static Variables,Instance Methods,假设我有一个程序: class Foo { public: unsigned int bar () { static unsigned int counter = 0; return counter++; } }; int main () { Foo a; Foo b; } (当然,这个例子毫无意义,因为我显然将“counter”声明为私有属性,但它只是为了说明问题) 我想知道C++在这种情况下的行为:BAR()方法中的变量“
class Foo {
public:
unsigned int bar () {
static unsigned int counter = 0;
return counter++;
}
};
int main ()
{
Foo a;
Foo b;
}
(当然,这个例子毫无意义,因为我显然将“counter”声明为私有属性,但它只是为了说明问题)
我想知道C++在这种情况下的行为:BAR()方法中的变量“计数器”对于每个实例是否相同?
< P>“每个实例都相同”,您的意思是在每个类实例中共享这个变量的一个实例,那么,是的,这是正确的。该类的所有实例都将使用相同的变量实例但请记住,对于类变量,在许多情况下必须考虑多线程之类的问题,这是一个完全不同的主题。是的,
计数器将在可执行文件中Foo
类型的对象的所有实例中共享。只要您处于单线程环境中,它就可以作为共享计数器正常工作
在多线程环境中,您将有一些有趣的竞赛条件要调试:(第二)从C++编程语言(200版),Bjarne Stroustrup:
除了在[普通]函数(§7.1.2)和类(§10.2.4)内,不要使用静态
你只需要掌握两件事:
静态变量存储在执行程序的静态区域(与全局变量的静态区域相同)
范围受括号的一般规则限制。此外,静态变量具有内部链接
您的示例离您可以编译和测试的内容还有几行:
#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;
}
因此,是的,计数器在所有实例中共享。假设编译器尚未为您处理此问题。语言定义是,变量在方法的所有调用中都是一致的。因此,这是编译器的任务,因此在多线程语言(下一版本的C++)中,这是编译器的任务。在此版本中,它取决于编译器与线程库的集成。gcc已经涵盖了这一点,并保证跨多个线程访问静态变量是安全的。@Martin York:也就是说,C++0x中的静态变量保证是线程本地的?多么有趣,可能会让一些人大吃一惊。就像一个漂亮的静态类实例计数器。突然之间,您将计算每个线程的实例。我不敢相信他们会做出这样的改变。你确定?!真正地这可能会破坏大量的代码。我无法想象委员会能收支平衡。001%的现有代码。@Omnifarious:你到底是怎么从我的声明中得到的!!这将是一个使用符号的完全改变。我相信你一定是疯了才想出那种解释。不,编译器(在语言级别)必须保证变量的符号。如果语言是多线程的,那么它必须保证对varibale的访问是线程安全的(即原子的。在一个线程中int的增量必须在另一个线程中立即可用)。目前,gcc已经保证了这一点。注意:这并不意味着需要保证对方法的访问是线程安全的。但这确实意味着不能基于每个处理器缓存状态。注2:此保证仅在语言具有内置线程的概念时可用(C++没有,但C++0x会)。生命周期不是程序的生命周期。从第一次使用(可能永远不会)到销毁(与创建静态变量的顺序相反)。Alos note初始化很好,因为它是函数的一部分,而不是类的一部分。@niel。。我的错!!我没有看到最后一句是关于命名空间范围静态变量的。局部静态变量(如问题中的变量)没有链接。(无法引用来自不同作用域的局部变量。如何引用在main中定义的变量?main()::v
不起作用)。规则非常棒。但只有在正确的上下文中使用。nieve用户可以将报价提交给hart。如果你要引用这样的话,你必须包含完整的上下文。有趣的是,你的输出是一个完美的例子,说明了序列点和执行顺序是如何工作的,并且可能导致违反直觉的结果。
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