std::unique_ptr::operator=
Материал из cppreference.com
< cpp | memory | unique ptr
unique_ptr& operator=( unique_ptr&& r ) noexcept; |
(1) | (constexpr начиная с C++23) |
template< class U, class E > unique_ptr& operator=( unique_ptr<U,E>&& r ) noexcept; |
(2) | (constexpr начиная с C++23) |
unique_ptr& operator=( std::nullptr_t ) noexcept; |
(3) | (constexpr начиная с C++23) |
unique_ptr& operator=( const unique_ptr& ) = delete; |
(4) | |
1) Оператор присваивания перемещением. Передаёт право собственности из r в *this, как если бы вызовом reset(r.release()) с последующим присваиванием get_deleter() из std::forward<Deleter>(r.get_deleter()).
Эта перегрузка участвует в разрешении перегрузки, только если std::is_move_assignable<Deleter>::value равно true.
Если
Deleter
не является ссылочным типом, поведение не определено, если
-
Deleter
не является MoveAssignable, или - присваивание get_deleter() из rvalue типа
Deleter
вызывает исключение.
Иначе (
Deleter
является ссылочным типом), поведение не определено, если
-
std::remove_reference<Deleter>::type
не является CopyAssignable, или - присваивание get_deleter() из lvalue типа
Deleter
вызывает исключение.
2) Преобразующий оператор присваивания. Передаёт право собственности из r в *this, как если бы вызовом reset(r.release()) с последующим присваиванием get_deleter() из std::forward<E>(r.get_deleter()).
Для основного шаблона эта перегрузка участвует в разрешении перегрузки, только если
-
U
не является типом массива, -
unique_ptr<U, E>::pointer
неявно преобразуется вpointer
, и - std::is_assignable<Deleter&, E&&>::value равно true.
Для специализации массива (
unique_ptr<T[]>
) эта перегрузка участвует в разрешении перегрузки, только если
-
U
это тип массива, -
pointer
имеет тот же тип, что иelement_type*
, -
unique_ptr<U, E>::pointer
имеет тот же тип, что иunique_ptr<U, E>::element_type*
, -
unique_ptr<U, E>::element_type(*)[]
преобразуется вelement_type(*)[]
, и - std::is_assignable<Deleter&, E&&>::value равно true.
Если
E
не является ссылочным типом, поведение не определено, если присваивание get_deleter() из rvalue типа E
некорректно или вызывает исключение. Иначе (
E
является ссылочным типом) поведение не определено, если присваивание get_deleter() из lvalue типа E
некорректно или вызывает исключение.3) Фактически то же самое, что и вызов reset().
4) Оператор присваивания копированием явно удалён.
Содержание |
[править] Параметры
r | — | умный указатель, от которого будет передано право собственности |
[править] Возвращаемое значение
*this
[править] Примечание
Как тип, предназначенный только для перемещения, оператор присваивания unique_ptr
принимает только аргументы rvalues (например, результат std::make_unique или std::move переменной unique_ptr
).
[править] Пример
Запустить этот код
#include <iostream> #include <memory> struct Foo { int id; Foo(int id) : id(id) { std::cout << "Foo " << id << '\n'; } ~Foo() { std::cout << "~Foo " << id << '\n'; } }; int main() { std::unique_ptr<Foo> p1( std::make_unique<Foo>(1) ); { std::cout << "Создание нового Foo...\n"; std::unique_ptr<Foo> p2( std::make_unique<Foo>(2) ); // p1 = p2; // Ошибка ! нельзя скопировать unique_ptr p1 = std::move(p2); std::cout << "Собираюсь покинуть внутренний блок...\n"; // Экземпляр Foo будет продолжать жить, несмотря на то, // что p2 выходит из области видимости } std::cout << "Выхожу из программы...\n"; }
Вывод:
Foo 1 Создание нового Foo... Foo 2 ~Foo 1 Собираюсь покинуть внутренний блок... Выхожу из программы... ~Foo 2
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 2047 | C++11 | для перегрузки (2), get_deleter() присваивался из std::forward<Deleter>(r.get_deleter()) |
исправлено на std::forward<E>(r.get_deleter()) |
LWG 2118 | C++11 | unique_ptr<T[]>::operator= отклоняет квалификационныепреобразования |
принимает |
LWG 2228 | C++11 | преобразующий оператор присваивания не был ограничен | ограничен |
LWG 2899 | C++11 | оператор присваивания перемещением не был ограничен | ограничен |