В качестве альтернативы можно также возвратить копию локального объекта:

unique_ptr clone(int p) {

 unique_ptr ret(new int(p));

 // ...

 return ret;

}

В обоих случаях компилятор знает, что возвращаемый объект будет сейчас удален. В таких случаях компилятор осуществляет специальный вид "копирования", обсуждаемый в разделе 13.6.2.

Совместимость с прежней версией: класс auto_ptr

Прежние версии библиотеки включали класс auto_ptr, обладавший некоторыми, но не всеми, свойствами указателя unique_ptr. В частности, невозможно было хранить указатели auto_ptr в контейнере и возвращать их из функции.

Хотя указатель auto_ptr все еще присутствует в стандартной библиотеке, вместо него следует использовать указатель unique_ptr.

Передача функции удаления указателю unique_ptr

Подобно указателю shared_ptr, для освобождения объекта, на который указывает указатель unique_ptr, по умолчанию используется оператор delete. Подобно указателю shared_ptr, функцию удаления указателя unique_ptr (см. раздел 12.1.4) можно переопределить. Но по причинам, описанным в разделе 16.1.6, способ применения функции удаления указателем unique_ptr отличается от такового у shared_ptr.

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

// p указывает на объект типа objT и использует объект типа delT

// для его освобождения

// он вызовет объект по имени fcn типа delT

unique_ptr p(new objT, fcn);

В качестве несколько более конкретного примера перепишем программу соединения так, чтобы использовать указатель unique_ptr вместо указателя shared_ptr следующим образом:

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

 connection c = connect(&d); // открыть соединение

 // когда p будет удален, соединение будет закрыто

 unique_ptr

  p(&с, end_connection);

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

 // по завершении f(), даже при исключении, соединение будет

 // закрыто правильно

}

Для определения типа указателя на функцию используется ключевое слово decltype (см. раздел 2.5.3). Поскольку выражение decltype(end_connection) возвращает тип функции, следует добавить символ *, указывающий, что используется указатель на этот тип (см. раздел 6.7).

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

Упражнение 12.16. Компиляторы не всегда предоставляют понятные сообщения об ошибках, если осуществляется попытка скопировать или присвоить указатель unique_ptr. Напишите программу, которая содержит эти ошибки, и посмотрите, как компилятор диагностирует их.

Упражнение 12.17. Какие из следующих объявлений указателей unique_ptr недопустимы или вероятнее всего приведут к ошибке впоследствии? Объясните проблему каждого из них.

int ix = 1024, *pi = &ix, *pi2 = new int(2048);

typedef unique_ptr IntP;

(a) IntP p0(ix);            (b) IntP p1(pi);

(c) IntP p2(pi2);           (d) IntP p3(&ix);

(e) IntP p4(new int(2048)); (f) IntP p5(p2.get());

Упражнение 12.18. Почему класс указателя shared_ptr не имеет функции-члена release()?

<p><image l:href="#books.png"/>12.1.6. Класс <code>weak_ptr</code></p>
Перейти на страницу:

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