Простейший аналог shared_ptr с конструктором по умолчанию

Пустой SharedPtr хранит нулевые указатели на объект и счётчик. Копирование увеличивает счётчик, перемещение передаёт владение, а последний владелец удаляет объект и счётчик.

Короткий ответ

Что ответить на собеседовании

Пустой SharedPtr хранит нулевые указатели на объект и счётчик. Копирование увеличивает счётчик, перемещение передаёт владение, а последний владелец удаляет объект и счётчик.

Подробный разбор

Ответ с пояснениями

Условие

Реализуйте базовый вариант умного указателя, который будет имитировать работу стандартного std::shared_ptr. Важно обеспечить наличие конструктора без параметров, позволяющего создавать пустой объект указателя.


template<typename T>
class SharedPtr {
    // TODO: реализация
};

Ответ

Пустой SharedPtr хранит нулевые указатели на объект и счётчик. Копирование увеличивает счётчик, перемещение передаёт владение, а последний владелец удаляет объект и счётчик.

Учебный однопоточный вариант для одного объекта, без массивов и пользовательских deleter:

#include <cstddef>
#include <utility>

template<class T>
class SharedPtr {
    T* ptr = nullptr;
    std::size_t* count = nullptr;
public:
    SharedPtr() noexcept = default;
    explicit SharedPtr(T* p) : ptr(p) {
        if (!p) return;
        try { count = new std::size_t(1); }
        catch (...) { delete p; throw; }
    }
    SharedPtr(const SharedPtr& other) noexcept
        : ptr(other.ptr), count(other.count) {
        if (count) ++*count;
    }
    SharedPtr(SharedPtr&& other) noexcept
        : ptr(std::exchange(other.ptr, nullptr)),
          count(std::exchange(other.count, nullptr)) {}
    SharedPtr& operator=(SharedPtr other) noexcept {
        std::swap(ptr, other.ptr);
        std::swap(count, other.count);
        return *this;
    }
    ~SharedPtr() {
        if (count && --*count == 0) {
            delete ptr;
            delete count;
        }
    }
    T* get() const noexcept { return ptr; }
    explicit operator bool() const noexcept { return ptr != nullptr; }
};

Присваивание через временный объект корректно обрабатывает самоприсваивание и освобождает прежнее владение. Нельзя дважды создавать независимых владельцев из одного сырого указателя. Этот пример не реализует weak_ptr, aliasing и потокобезопасный управляющий блок стандартного shared_ptr.

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

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

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

Подробнее