Пустой SharedPtr хранит нулевые указатели на объект и счётчик. Копирование увеличивает счётчик, перемещение передаёт владение, а последний владелец удаляет объект и счётчик.
Простейший аналог shared_ptr с конструктором по умолчанию
Пустой 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.