std::unique_ptr::operator=
Материал из cppreference.com
<tbody>
</tbody>
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 | оператор присваивания перемещением не был ограничен | ограничен |