Что такое умные указатели в C++, какие бывают и в чем их отличие
Что проверяют
Понимаете ли вы владение и RAII. Вопрос не про названия классов, а про то, кто отвечает за время жизни объекта.
Как отвечать
Умный указатель это объект, который владеет ресурсом и освобождает его в своём деструкторе. Это RAII: память возвращается при выходе из области видимости, в том числе когда выход происходит через исключение.
- unique_ptr: единственный владелец. Копировать нельзя, можно переместить. По размеру и скорости равен сырому указателю. Вариант по умолчанию;
- shared_ptr: разделяемое владение через счётчик ссылок. Объект жив, пока счётчик не ноль. Платите атомарным счётчиком и отдельным блоком управления;
- weak_ptr: наблюдатель без владения. Счётчик не увеличивает, перед обращением превращается в shared_ptr через
lock().
auto p = std::make_unique<Node>(); // владелец один
auto s = std::make_shared<Node>(); // объект и счётчик одним выделением
std::weak_ptr<Node> w = s; // жизнь не продлеваетСоздавайте через make_unique и make_shared: одно выделение памяти вместо двух и безопасность, если исключение случится при вычислении аргументов.
Где спотыкаются
Берут shared_ptr везде по привычке. Разделяемое владение это редкий случай, а атомарный счётчик стоит тактов на каждом копировании.
Не знают про циклы: два shared_ptr друг на друга не освободятся никогда, разрывается weak_ptr.
Передают shared_ptr по значению в каждую функцию, хотя функция ничем не владеет и ей хватит ссылки или сырого указателя.
Забывают, что для массива нужен unique_ptr<T[]>, иначе вызовется delete вместо delete[].