静态与成员变量

时间:2009-03-09 09:14:38

标签: c++ debugging static variables

对于调试,我想在我的课程中添加一些计数器变量。但是,如果不更改标题以进行大量重新编译,那么这样做会很好。

如果我正确理解了关键字,以下两个代码段将完全相同。当然假设只有一个实例。

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的计数在所有类的实例之间共享,但在我的情况下这不是问题。

  • 这是否正确使用了关键字?我假设一旦计数 FooB 中创建,它就会保持创建状态,并且不会在每次更新调用时重新初始化为零。
  • 我应该注意其他任何警告或抬头吗?

编辑:在收到通知,这会导致多线程环境出现问题后,我澄清说我的代码库是单线程的。

4 个答案:

答案 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;
}