对于调试,我想在我的课程中添加一些计数器变量。但是,如果不更改标题以进行大量重新编译,那么这样做会很好。
如果我正确理解了关键字,以下两个代码段将完全相同。当然假设只有一个实例。
class FooA
{
public:
FooA() : count(0) {}
~FooA() {}
void update()
{
++count;
}
private:
int count;
};
VS
class FooB
{
public:
FooB() {}
~FooB() {}
void update()
{
static int count = 0;
++count;
}
};
在 FooA 中,可以在类中的任何位置访问计数,并且还会使标题膨胀,因为变量应该在不再需要时被删除。
在 FooB 中,变量仅在其存在的一个函数中可见。以后容易删除。我能想到的唯一缺点就是FooB的计数在所有类的实例之间共享,但在我的情况下这不是问题。
编辑:在收到通知,这会导致多线程环境出现问题后,我澄清说我的代码库是单线程的。
答案 0 :(得分:3)
您对静态函数变量的假设是正确的。如果从多个线程访问它,则可能不正确。考虑使用InterlockedIncrement()。
答案 1 :(得分:2)
您真正想要的是,对于您的长期而言,C ++工具箱是一个线程安全的通用调试计数器类,允许您将其放在任何地方并使用它,并且可以从其他任何地方访问以进行打印。如果您的代码对性能敏感,那么您可能希望它在非调试版本中自动执行任何操作。
这样一个类的接口可能如下所示:
class Counters {
public:
// Counters singleton request pattern.
// Counters::get()["my-counter"]++;
static Counters& get() {
if (!_counters) _counters = new Counters();
}
// Bad idea if you want to deal with multithreaded things.
// If you do, either provide an Increment(int inc_by); function instead of this,
// or return some sort of atomic counter instead of an int.
int& operator[](const string& key) {
if (__DEBUG__) {
return _counter_map.operator[](key);
} else {
return _bogus;
}
}
// you have to deal with exposing iteration support.
private:
Counters() {}
// Kill copy and operator=
void Counters(const Counters&);
Counters& operator=(const Counters&);
// Singleton member.
static Counters* _counters;
// Map to store the counters.
std::map<string, int> _counter_map;
// Bogus counter for opt builds.
int _bogus;
};
完成此操作后,您可以通过调用以下方式随意将其放入.cpp文件中的任何位置:
void Foo::update() {
// Leave this in permanently, it will automatically get killed in OPT.
Counters::get()["update-counter"]++;
}
在你的主要内容中,如果你有内置的迭代支持,你可以:
int main(...) {
...
for (Counters::const_iterator i = Counters::get().begin(); i != Countes::get().end(); ++i) {
cout << i.first << ": " << i.second;
}
...
}
创建计数器类有点重,但是如果你正在进行一堆cpp编码,你可能会发现编写一次然后能够将它作为任何lib的一部分链接它是有用的。
答案 2 :(得分:1)
当静态变量与多线程一起使用时,会出现主要问题。如果您的应用程序是单线程的,那么您正在做的事情非常正确。
答案 3 :(得分:1)
在这种情况下我通常做的是将count放入类的源文件中的匿名命名空间中。这意味着您可以随意添加/删除变量,它可以在文件中的任何位置使用,并且不存在名称冲突的可能性。它的缺点是它只能用在源文件中的函数中,而不能用在头文件中的内联函数中,但我认为这就是你想要的。
在文件FooC.cpp
中namespace {
int count=0;
}
void FooC::update()
{
++count;
}