По умолчанию указатели shared_ptr подразумевали, что они указывают на динамическую память. Следовательно, когда указатель shared_ptr удаляется, он по умолчанию выполняет оператор delete для содержащегося в нем указателя. Чтобы использовать указатель shared_ptr для управления соединением connection, следует сначала определить функцию, используемую вместо оператора delete. Должна быть возможность вызова этой функции удаления (deleter) с указателем, хранимым в указателе shared_ptr. В данном случае функция удаления должна получать один аргумент типа connection*:

void end_connection(connection *p) { disconnect(*p); }

При создании указателя shared_ptr можно передать необязательный аргумент, указывающий на функцию удаления (см. раздел 6.7):

void f(destination &d /* другие параметры */) {

 connection с = connect(&d);

 shared_ptr p(&c, end_connection);

 // использовать соединение

 // при выходе из функции f(), даже в случае исключения, соединение

 // будет закрыто правильно

}

При удалении указателя p для хранимого в нем указателя вместо оператора delete будет вызвана функция end_connection(). Функция end_connection(), в свою очередь, вызовет функцию disconnect(), гарантируя таким образом закрытие соединения. При нормальном выходе из функции f() указатель p будет удален в ходе процедуры выхода. Кроме того, указатель p будет также удален, а соединение закрыто, если произойдет исключение.

Внимание! Проблемы интеллектуального указателя

Интеллектуальные указатели могут обеспечить безопасность и удобство работы с динамически созданной памятью только при правильном использовании. Для этого следует придерживаться ряда соглашений.

• Не используйте значение того же встроенного указателя для инициализации (переустановки) нескольких интеллектуальных указателей.

• Не используйте оператор delete для указателя, возвращенного функцией get().

• Не используйте функцию get() для инициализации или переустановки другого интеллектуального указателя.

• Используя указатель, возвращенный функцией get(), помните, что указатель станет недопустимым после удаления последнего соответствующего интеллектуального указателя.

• Если интеллектуальный указатель используется для управления ресурсом, отличным от области динамической памяти, зарезервированной оператором new, не забывайте использовать функцию удаления (раздел 12.1.4 и раздел 12.1.5).

Упражнения раздела 12.1.4

Упражнение 12.14. Напишите собственную версию функции, использующую указатель shared_ptr для управления соединением.

Упражнение 12.15. Перепишите первое упражнение так, чтобы использовать лямбда-выражение (см. раздел 10.3.2) вместо функции end_connection().

<p>12.1.5. Класс <code>unique_ptr</code></p>

Указатель unique_ptr "владеет" объектом, на который он указывает. В отличие от указателя shared_ptr, только один указатель unique_ptr может одновременно указывать на данный объект. Объект, на который указывает указатель unique_ptr, удаляется при удалении указателя. Список функций, специфических для указателя unique_ptr, приведен в табл. 12.4. Функции, общие для обоих указателей, приведены в табл. 12.1.

В отличие от указателя shared_ptr, нет никакой библиотечной функции, подобной функции make_shared(), которая возвращала бы указатель unique_ptr. Вместо этого определяемый указатель unique_ptr связывается с указателем, возвращенным оператором new. Подобно указателю shared_ptr, можно использовать прямую форму инициализации:

unique_ptr p1; // указатель unique_ptr на тип double

Перейти на страницу:

Похожие книги