Переданный T* сохраняется как управляемый ресурс, а отдельный счётчик создаётся со значением 1. Важно освободить принятый ресурс, если выделение памяти под счётчик завершится ошибкой.
SharedPtr: реализация конструктора, принимающего сырой указатель
Переданный T* сохраняется как управляемый ресурс, а отдельный счётчик создаётся со значением 1. Важно освободить принятый ресурс, если выделение памяти под счётчик завершится ошибкой.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо реализовать конструктор класса‑шаблона, который принимает указатель типа T*. Конструктор обязан присвоить полученный указатель полю m_ptr и инициализировать счётчик ссылок m_counter значением 1.
template <class T>
class SharedPtr {
int* m_counter = nullptr;
T* m_ptr = nullptr;
public:
SharedPtr() = default;
SharedPtr(const SharedPtr& p) {
m_ptr = p.m_ptr;
m_counter = p.m_counter;
(*m_counter)++;
}
SharedPtr(T* ptr) {
m_ptr = ptr;
m_counter = new int(1);
}
};
Ответ
Переданный T* сохраняется как управляемый ресурс, а отдельный счётчик создаётся со значением 1. Важно освободить принятый ресурс, если выделение памяти под счётчик завершится ошибкой.
Для владения одним объектом, созданным через new:
explicit SharedPtr(T* ptr) : m_ptr(ptr) {
try {
m_counter = new int(1);
} catch (...) {
delete ptr;
throw;
}
}
В этом контракте даже переданный nullptr получает счётчик 1, тогда как конструктор без параметров оставляет его пустым. Показанный копирующий конструктор также надо защитить проверкой if (m_counter): копирование пустого указателя иначе разыменует nullptr. Для полноценного владения нужны деструктор и корректное присваивание.