template class SharedPtr { private: Type* ptr_; int* count; public: // Инициализируем счетчик ссылок в 1 // (конструктор создает первый SharedPtr, который хранит указатель) explicit SharedPtr(Type *ptr = 0) { if (ptr != 0) count = new int(1); ptr_ = ptr; } // В деструкторе мы уменьшаем значение счетчика на 1, // если в объекте SharedPtr хранится ненулевой указатель // (мы удаляем один SharedPtr, который указывает на объект в куче) ~SharedPtr() { if (ptr_ != 0) { (*count)--; if (*count == 0) { delete ptr_; delete count; } } } // В конструкторе копирования мы увеличиваем счетчик ссылок на 1, // если копируемый SharedPtr содержит ненулевой указатель // (конструктор копирования создает еще один SharedPtr с указателем на тот же самый объект) SharedPtr(const SharedPtr &ptr) { if (ptr.ptr_ != 0) { (*(ptr.count))++; count = ptr.count; } ptr_ = ptr.ptr_; } // Оператор присваивания уменьшает счетчик ссылок левого операнда на 1, // если внутри левого SharedPtr хранится ненулевой указатель, // увеличивает счетчик правого SharedPtr на 1, // если в правом SharedPtr хранится ненулевой указатель // (обычное дело для оператора присваивания — сначала освобождаем старые ресурсы, // потом выделяем новые, // но при этом нужно быть особенно внимательным с присваиванием самому себе). SharedPtr& operator=(const SharedPtr &ptr) { if (this != &ptr) { if (ptr_ != 0) { (*count)--; if (*(count) == 0) { delete ptr_; delete count; } } if (ptr.ptr_ != 0) { (*(ptr.count))++; count = ptr.count; } ptr_ = ptr.ptr_; } return *this; } // Освобождаем старый указатель, и захватываем новый void reset(Type *ptr = 0) { if (ptr_ != 0) { (*count)--; if (*(count) == 0) { delete ptr_; delete count; } } ptr_ = ptr; if (ptr_ != 0) count = new int(1); } // Возвращает указатель, сохраненный внутри Shared // (например, чтобы передать его в какую-то функцию) Type* get() const { return ptr_; } Type& operator*() const { return *ptr_; } Type* operator->() const { return ptr_; } };