如何在程序中安全(并且轻松)计算类的所有*实例?

时间:2010-07-19 01:31:42

标签: c++

我希望能够实例化一个特定的(和其他正常的)类(我可以修改它的源)并计算该类被实例化的次数(例如like this)。但是我希望将所有实例都包括在我的总计数中,甚至包括通过标准容器中的复制构造函数创建的实例。

让我的类的所有构造函数(包括复制构造函数)增加静态计数器是否合适?如果是这样,是否可以通过覆盖其他运算符来确保我的类仍然符合标准容器的要求(即T(x)等于x)?

2 个答案:

答案 0 :(得分:9)

实现此目的的常用方法是使用您继承的类模板。

template <typename T>
class Countable
{
    static unsigned cs_count_;
public:
    Countable() { ++cs_count_; }
    Countable( Countable const& ) { ++cs_count_; }
    virtual ~Countable() { --cs_count_; }
    static unsigned count() { return cs_count_; }
};

template <typename T>
unsigned Countable<T>::cs_count_ = 0;

所以要使用它我会写:

class MyClass : public Countable<MyClass> { };

以下是线程安全版本。它使用boost中的类来确保增量,减量和读取操作在支持的平台上是原子的。

#include <boost/detail/atomic_count.hpp>

template <typename T>
class Countable
{
    static boost::detail::atomic_count cs_count_;
protected:
    ~Countable() { --cs_count_; }
public:
    Countable() { ++cs_count_; }
    Countable( Countable const& ) { ++cs_count_; }
    static unsigned count() { return cs_count_; }
};

template <typename T>
boost::detail::atomic_count Countable<T>::cs_count_(0);

答案 1 :(得分:8)

将静态类变量视为全局变量,它位于类的命名空间中。使用它增加或执行其他操作不会对其他代码产生任何副作用,即构造函数和其他运算符的行为与以前完全相同。

即,你是对的:只需在构造函数中递增并在析构函数中递减。


当然,正如George指出的那样,如果你想让多线程安全,你需要在访问你的计数器变量(例如一些互斥锁)时添加一些多线程安全代码。或者正如Steven指出的那样,您也可以使用原子递增/递减指令(但用法取决于平台)。那些会快得多。但是,你必须要小心,因为在某些情况下,它不适用于多处理器环境。你可以使用Boost的atomic_count来保证安全。