Базовая реализация собственного 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.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее