Как может, я безопасно (и легко) рассчитываю *все* экземпляры класса в рамках моей программы?

Я хотел бы смочь инстанцировать детали (и в других отношениях нормальный) класс (источник которого я могу изменить) и считают количество раз, класс инстанцировали (например, как это). Но я хотел бы включать все экземпляры в свое общее количество, даже некоторые, которые создаются через конструктора копии в стандартных контейнерах.

Было бы уместно иметь всех конструкторов (включая конструктора копии) моего инкремента класса статический счетчик? Если так, действительно ли возможно гарантировать, что мой класс все еще соответствует требованиям стандартных контейнеров (т.е. T (x) эквивалентен x) путем переопределения других операторов, например?

6
задан Community 23 May 2017 в 10:27
поделиться

2 ответа

Думайте о статической переменной класса как о глобальной переменной, которая находится как раз в пространстве имен класса. Увеличение или выполнение других действий с ним не будет иметь никаких побочных эффектов для другого кода, то есть ваши конструкторы и другие операторы будут вести себя точно так же, как и раньше.

То есть, вы правы: просто увеличивайте все конструкторы и уменьшайте в деструкторе.


Конечно, как указал Джордж, если вы хотите, чтобы многопоточность была безопасной, вам нужно добавить некоторый безопасный многопоточный код для доступа к вашей переменной счетчика (например, некоторый мьютекс). Или, как указал Стивен, вы также можете использовать атомарные инструкции увеличения / уменьшения (но использование будет зависеть от платформы). Это было бы намного быстрее. Тем не менее, вы должны быть осторожны, потому что в некоторых случаях это не работает в многопроцессорных средах. Вы можете использовать Boost's atomic_count на всякий случай.

8
ответ дан 8 December 2019 в 13:43
поделиться

Обычно это достигается с помощью шаблона класса, от которого вы наследуете.

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);
9
ответ дан 8 December 2019 в 13:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: