Упрощённый shared_ptr хранит общий счётчик владельцев: копирование увеличивает его, разрушение уменьшает, а последний владелец удаляет ресурс и счётчик.
Базовая реализация собственного shared_ptr
Упрощённый shared_ptr хранит общий счётчик владельцев: копирование увеличивает его, разрушение уменьшает, а последний владелец удаляет ресурс и счётчик.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо реализовать упрощённую версию умного указателя типа shared_ptr. Класс должен хранить указатель на объект и счётчик ссылок, а также обеспечивать корректную работу конструктора, деструктора, копирующего конструктора и операторов доступа к управляемому объекту.
template<typename T>
class SimpleSharedPtr {
T* resource; // указатель на управляемый объект
int* refCount; // счётчик ссылок
public:
// конструктор, деструктор, копирующий конструктор, оператор присваивания и доступ к объекту
};
Ответ
Упрощённый shared_ptr хранит общий счётчик владельцев: копирование увеличивает его, разрушение уменьшает, а последний владелец удаляет ресурс и счётчик.
Учебный вариант для одиночного объекта и одного потока:
#include <cstddef>
#include <utility>
template<class T>
class SimpleSharedPtr {
T* resource = nullptr;
std::size_t* refCount = nullptr;
public:
explicit SimpleSharedPtr(T* p = nullptr) : resource(p) {
if (p) {
try { refCount = new std::size_t(1); }
catch (...) { delete p; throw; }
}
}
SimpleSharedPtr(const SimpleSharedPtr& p) noexcept
: resource(p.resource), refCount(p.refCount) {
if (refCount) ++*refCount;
}
SimpleSharedPtr(SimpleSharedPtr&& p) noexcept {
swap(p);
}
~SimpleSharedPtr() {
if (refCount && --*refCount == 0) {
delete resource;
delete refCount;
}
}
void swap(SimpleSharedPtr& p) noexcept {
std::swap(resource, p.resource);
std::swap(refCount, p.refCount);
}
SimpleSharedPtr& operator=(SimpleSharedPtr p) noexcept {
swap(p);
return *this;
}
T& operator*() const { return *resource; }
T* operator->() const noexcept { return resource; }
};
Copy-and-swap учитывает самоприсваивание. Разыменование пустого указателя недопустимо. Здесь нет поддержки массивов, weak_ptr, циклов владения и потокобезопасного счётчика. Нельзя создавать два независимых владельца от одного raw pointer. В рабочем коде предпочтителен std::shared_ptr.