Тип дебетора в unique_ptr vs. shared_ptr
Я подумал, что очень любопытно, когда я обнаружил, что стандарт определяет std::unique_ptr
и std::shared_ptr
двумя совершенно разными способами относительно Deleter, которыми может владеть указатель. Вот объявление из cppreference:: unique_ptr и cppreference:: shared_ptr:
template<
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
template< class T > class shared_ptr;
Как вы видите, unique_ptr "сохраняет" тип объекта Deleter в качестве аргумента шаблона. Это также можно увидеть в способе удаления Deleter из указателя позже:
// unique_ptr has a member function to retrieve the Deleter
template<
class T,
class Deleter = std::default_delete<T>
>
Deleter& unique_ptr<T, Deleter>::get_deleter();
// For shared_ptr this is not a member function
template<class Deleter, class T>
Deleter* get_deleter(const std::shared_ptr<T>& p);
Может кто-нибудь объяснить рациональность этой разницы? Я явно одобряю концепцию unique_ptr
, почему это не относится к shared_ptr
? Кроме того, почему get_deleter
была бы не-членной функцией в последнем случае?
Ответы
Ответ 1
Здесь вы можете найти оригинальное предложение для интеллектуальных указателей: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html
Он точно отвечает на ваш вопрос:
Поскольку делетер не является частью типа, изменение стратегии распределения не нарушает совместимость с исходным кодом или двоичным кодом и не требует перекомпиляции клиента.
Это также полезно, поскольку дает клиентам std::shared_ptr
некоторую дополнительную гибкость, например, экземпляры shared_ptr
с разными удалениями могут храниться в одном контейнере.
Кроме того, поскольку реализация shared_ptr
нуждается в блоке разделяемой памяти так или иначе (для хранения счетчика ссылок), и потому, что alreay должен быть накладными расходами по сравнению с необработанными указателями, добавление удаляемого типа удаления не является большим сделка здесь.
unique_ptr
, с другой стороны, не имеют никаких накладных расходов, и каждый экземпляр должен внедрить свой делетер, поэтому сделать его частью этого типа является естественным делом.