Данные классы отличаются также тем, как они позволяют пользователям переопределять свою стандартную функцию удаления. Для переопределения функции удаления класса shared_ptr
reset()
. У объекта класса unique_ptr
, напротив, тип функции удаления является частью типа. При определении указателя unique_ptr
пользователи должны предоставлять этот тип как явный аргумент шаблона. В результате для указателя unique_ptr
сложней предоставить собственную функцию удаления.Различие в способе работы функции удаления — это лишь частность функциональных возможностей данных классов. Но, как будет вскоре продемонстрировано, это различие в стратегии реализации может серьезно повлиять на производительность.
Даже не зная, как именно реализуются библиотечные типы, вполне можно догадаться, что указатель shared_ptr
function
из раздела 14.8.3), инкапсулирующий указатель.То, что тип функции удаления не известен до времени выполнения, позволяет убедиться, что класс shared_ptr
shared_ptr
позволяет изменить тип функции удаления на протяжении продолжительности его существования. Вполне можно создать указатель shared_ptr
, используя функцию удаления одного типа, а впоследствии использовать функцию reset()
, чтобы использовать для того же указателя shared_ptr
другой тип функции удаления. Вообще, у класса не может быть члена, тип которого изменяется во время выполнения. Следовательно, функция удаления должна храниться отдельно.Размышляя о том, как должна работать функция удаления, предположим, что класс shared_ptr
p
, а обращение к функции удаления осуществляется через член класса по имени del
. Деструктор класса shared_ptr
должен включать такой оператор://
//
del ? del(p) : delete p; //
//
Поскольку функция удаления хранится отдельно, вызов del(p)
del
и выполнения кода, на который он указывает.Теперь давайте подумаем, как мог бы работать класс unique_ptr
unique_ptr
. Таким образом, у шаблона unique_ptr
есть два параметра шаблона: представляющий контролируемый указатель и представляющий тип функции удаления. Поскольку тип функции удаления является частью типа unique_ptr
, тип функции-члена удаления известен на момент компиляции. Функция удаления может храниться непосредственно в каждом объекте класса unique_ptr
.Деструктор класса unique_ptr
shared_ptr
, в котором он вызывает предоставленную пользователем функцию удаления или выполняет оператор delete
для хранимого указателя://
//
del(p); //
Тип del
DebugDelete
(см. раздел 16.1.4), этот вызов мог бы даже быть встраиваемым во время компиляции.При привязке функции удаления во время компиляции класс unique_ptr
shared_ptr
облегчает пользователю переопределение функции удаления.Упражнение 16.28
. Напишите собственные версии классовshared_ptr
и unique_ptr
.Упражнение 16.29
. Пересмотрите свой классBlob
так, чтобы использовать собственную версию класса shared_ptr
, а не библиотечную.