std::unique_ptr<T,Deleter>::operator=

来自cppreference.com
< cpp‎ | memory‎ | unique ptr
 
 
工具库
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(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)
 
动态内存管理
未初始化内存算法
受约束的未初始化内存算法
分配器
垃圾收集支持
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)



 
 
unique_ptr& operator=( unique_ptr&& r ) noexcept;
(1) (C++23 起 constexpr)
template< class U, class E >
unique_ptr& operator=( unique_ptr<U, E>&& r ) noexcept;
(2) (C++23 起 constexpr)
unique_ptr& operator=( std::nullptr_t ) noexcept;
(3) (C++23 起 constexpr)
unique_ptr& operator=( const unique_ptr& ) = delete;
(4)
1) 移动赋值运算符。从 r 转移所有权到 *this,如同在调用 reset(r.release()) 后立即将 std::forward<Deleter>(r.get_deleter()) 赋给 get_deleter()
此重载只有在 std::is_move_assignable<Deleter>::valuetrue 时才会参与重载决议。
如果 Deleter 不是引用类型,那么在以下情况下行为未定义:
否则(Deleter 是引用类型),那么在以下情况下行为未定义:
2) 转换赋值运算符。从 r 转移所有权到 *this,如同在调用 reset(r.release()) 后立即将 std::forward<E>(r.get_deleter()) 赋给 get_deleter()
对于主模板,此重载只有在满足以下所有条件时才会参与重载决议:
  • U 不是数组类型。
  • unique_ptr<U, E>::pointer 可以隐式转换到 pointer
  • std::is_assignable<Deleter&, E&&>::valuetrue
对于数组特化(unique_ptr<T[]>),此重载只有在满足以下所有条件时才会参与重载决议:
  • U 是数组类型。
  • pointerelement_type* 是同一类型。
  • unique_ptr<U, E>::pointerunique_ptr<U, E>::element_type* 是同一类型。
  • unique_ptr<U, E>::element_type(*)[] 可以转换到 element_type(*)[]
  • std::is_assignable<Deleter&, E&&>::valuetrue
如果 E 不是引用类型,那么在将 E 类型的右值赋给 get_deleter() 会非良构或者抛出异常时行为未定义。
否则(E 是引用类型),那么在将 E 类型的左值赋给 get_deleter() 会非良构或者抛出异常时行为未定义。
3) 与调用 reset() 等效。
4) 复制赋值运算符被显式删除。

参数

r - 所有权将被转移的智能指针

返回值

*this

注解

作为只能被移动的类型,unique_ptr 的赋值运算符只接受右值实参(例如 std::make_unique 的结果或已被 std::moveunique_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";
 
        // 即使 p2 将要离开作用域,但是 Foo 示例会继续生存
    }
 
    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 移动赋值运算符未受约束 已约束