Пространства имён
Варианты
Действия

std::unique_ptr::operator=

Материал из cppreference.com
< cpp‎ | memory‎ | unique ptr
 
 
Библиотека утилит
Языковая поддержка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования функциональности библиотеки (C++20)    
Управление динамической памятью
Программные утилиты
Поддержка сопрограмм (C++20)
Вариативные функции
Трёхстороннее сравнение (C++20)
(C++20)
(C++20)(C++20)(C++20)(C++20)(C++20)(C++20)
Общие утилиты
Дата и время
Функциональные объекты
Библиотека форматирования (C++20)
(C++11)
Операторы отношения (устарело в C++20)
Целочисленные функции сравнения
(C++20)(C++20)(C++20)    
(C++20)
Операции обмена и типа
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Общие лексические типы
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Элементарные преобразования строк
(C++17)
(C++17)
 
Динамическое управление памятью
no section name
Ограниченные алгоритмы неинициализированной памяти
no section name
Поддержка сбора мусора
(C++11)(до C++23)
(C++11)(до C++23)
(C++11)(до C++23)
(C++11)(до C++23)
(C++11)(до C++23)
(C++11)(до C++23)



no section name
 
 
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 является ссылочным типом), поведение не определено, если
  • 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 оператор присваивания перемещением не был ограничен ограничен