unique_ptr p2(new int(42)); // p2 указывает на int со значением 42

Таблица 12.4. Функции указателя unique_ptr (см. также табл. 12.1)

unique_ptr u1 unique_ptr u2Обнуляет указатель unique_ptr, способный указывать на объект типа Т. Указатель u1 использует для освобождения своего указателя оператор delete; а указатель u2 — вызываемый объект типа D
unique_ptr u(d)Обнуляет указатель unique_ptr, указывающий на объекты типа Т. Использует вызываемый объект d типа D вместо оператора delete
u = nullptrУдаляет объект, на который указывает указатель u; обнуляет указатель u
u.release()Прекращает контроль содержимого указателя u; возвращает содержимое указателя u и обнуляет его
u.reset() u.reset(q) u.reset(nullptr)Удаляет объект, на который указывает указатель u. Если предоставляется встроенный указатель q, то u будет указывать на его объект. В противном случае указатель u обнуляется

Поскольку указатель unique_ptr владеет объектом, на который указывает, он не поддерживает обычного копирования и присвоения:

unique_ptr p1(new string("Stegosaurus"));

unique_ptr p2(p1); // ошибка: невозможно копирование unique_ptr

unique_ptr p3;

p3 = p2; // ошибка: невозможно присвоение unique_ptr

Хотя указатель unique_ptr нельзя ни присвоить, ни скопировать, можно передать собственность от одного (неконстантного) указателя unique_ptr другому, вызвав функцию release() или reset():

// передает собственность от p1 (указывающего на

// строку "Stegosaurus") к p2

unique_ptr p2(p1.release()); // release() обнуляет p1

unique_ptr p3(new string("Trex"));

// передает собственность от p3 к p2

р2.reset(p3.release()); // reset() освобождает память, на которую

                        // указывал указатель p2

Функция-член release() возвращает указатель, хранимый в настоящее время в указателе unique_ptr, и обнуляет указатель unique_ptr. Таким образом, указатель p2 инициализируется указателем, хранимым в указателе p1, а сам указатель p1 становится нулевым.

Функция-член reset() получает необязательный указатель и переустанавливает указатель unique_ptr на заданный указатель. Если указатель unique_ptr не нулевой, то объект, на который он указывает, удаляется. Поэтому вызов функции reset() указателя p2 освобождает память, используемую строкой со значением "Stegosaurus", передает содержимое указателя p3 указателю p2 и обнуляет указатель p3.

Вызов функции release() нарушает связь между указателем unique_ptr и объектом, который он контролирует. Зачастую указатель, возвращенный функцией release(), используется для инициализации или присвоения другому интеллектуальному указателю. В этом случае ответственность за управление памятью просто передается от одного интеллектуального указателя другому. Но если другой интеллектуальный указатель не используется для хранения указателя, возвращенного функцией release(), то ответственность за освобождения этого ресурса берет на себя программа:

p2.release(); // ОШИБКА: p2 не освободит память, и указатель

              // будет потерян

auto p = p2.release(); // ok, но следует не забыть delete(p)

Передача и возвращение указателя unique_ptr

Из правила, запрещающего копирование указателя unique_ptr, есть одно исключение: можно копировать и присваивать те указатели unique_ptr, которые предстоит удалить. Наиболее распространенный пример — возвращение указателя unique_ptr из функции:

unique_ptr clone(int p) {

 // ok: явное создание unique_ptr для int*

 return unique_ptr(new int(p));

}

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

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