Namespaces
Variants

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

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
主模板 unique_ptr<T> 的成员
constexpr unique_ptr ( ) noexcept ;
constexpr unique_ptr ( std:: nullptr_t ) noexcept ;
(1)
explicit unique_ptr ( pointer p ) noexcept ;
(2) (自 C++23 起为 constexpr)
unique_ptr ( pointer p, /* see below */ d1 ) noexcept ;
(3) (自 C++23 起为 constexpr)
unique_ptr ( pointer p, /* see below */ d2 ) noexcept ;
(4) (自 C++23 起为 constexpr)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (自 C++23 起为 constexpr)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (自 C++23 起为 constexpr)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
template < class U >
unique_ptr ( std:: auto_ptr < U > && u ) noexcept ;
(8) (在 C++17 中移除)
数组特化版本 unique_ptr<T[]> 的成员
constexpr unique_ptr ( ) noexcept ;
constexpr unique_ptr ( std:: nullptr_t ) noexcept ;
(1)
template < class U >
explicit unique_ptr ( U p ) noexcept ;
(2) (自 C++23 起为 constexpr)
template < class U >
unique_ptr ( U p, /* see below */ d1 ) noexcept ;
(3) (自 C++23 起为 constexpr)
template < class U >
unique_ptr ( U p, /* see below */ d2 ) noexcept ;
(4) (自 C++23 起为 constexpr)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (自 C++23 起为 constexpr)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (自 C++23 起为 constexpr)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
1) 构造一个不持有任何资源的 std::unique_ptr 。对存储的指针和存储的删除器进行值初始化。要求 Deleter 满足 可默认构造 要求,且构造过程不会抛出异常。这些重载仅当 std:: is_default_constructible < Deleter > :: value true Deleter 不是指针类型时才参与重载决议。
2) 构造一个拥有 p std::unique_ptr ,使用 p 初始化存储的指针并对存储的删除器进行值初始化。要求 Deleter 满足 可默认构造 且构造过程不会抛出异常。此重载仅当 std:: is_default_constructible < Deleter > :: value true Deleter 不是指针类型时参与重载决议。

此构造函数不会被 类模板实参推导 选中。

(C++17 起)
3,4) 构造一个拥有 p std::unique_ptr 对象,使用 p 初始化存储的指针,并按以下方式初始化删除器 D (具体取决于 D 是否为引用类型)。
a) D 为非引用类型 A ,则函数签名为:
unique_ptr ( pointer p, const A & d ) noexcept ;
(1) (要求 Deleter 满足不抛出异常的 可复制构造 )
unique_ptr ( pointer p, A && d ) noexcept ;
(2) (要求 Deleter 满足不抛出异常的 可移动构造 )
b) D 为左值引用类型 A & ,则函数签名为:
unique_ptr ( pointer p, A & d ) noexcept ;
(1)
unique_ptr ( pointer p, A && d ) = delete ;
(2)
c) D 为左值引用类型 const A & ,则函数签名为:
unique_ptr ( pointer p, const A & d ) noexcept ;
(1)
unique_ptr ( pointer p, const A && d ) = delete ;
(2)
在所有情况下,删除器都从 std:: forward < decltype ( d ) > ( d ) 初始化。这些重载仅在 std:: is_constructible < D, decltype ( d ) > :: value true 时参与重载决议。

这两个构造函数不会被 类模板实参推导 选中。

(C++17 起)
2-4) 在数组特化版本中,其行为与主模板中接受指针参数的构造函数相同,但额外满足以下条件之一时才参与重载决议:
  • U pointer 类型相同,或
  • U std::nullptr_t ,或
  • pointer element_type* 类型相同,且 U 是某种指针类型 V* ,使得 V(*)[] 可隐式转换为 element_type(*)[]
5) 通过将所有权从 u 转移给 * this 来构造一个 unique_ptr ,并将空指针存入 u 。该构造函数仅当 std:: is_move_constructible < Deleter > :: value true 时参与重载决议。如果 Deleter 不是引用类型,要求其满足不抛出移动构造(若 Deleter 为引用类型,则移动构造后的 get_deleter() u.get_deleter() 将引用同一值)。
6) 通过将所有权从 u 转移给 * this 来构造一个 unique_ptr ,其中 u 使用指定的删除器( E )构造。具体行为取决于 E 是否为引用类型,如下所示:
a) E 为引用类型,则此删除器从 u 的删除器复制构造(要求该构造过程不抛出异常),
b) E 是非引用类型,则此删除器从 u 的删除器移动构造(要求该构造操作不抛出异常)。
当且仅当满足以下全部条件时,此构造函数才会参与重载决议:
a) unique_ptr < U, E > :: pointer 可隐式转换为 pointer
b) U 不是数组类型,
c) 满足以下任一条件: Deleter 是引用类型且 E Deleter 类型相同,或 Deleter 不是引用类型且 E 可隐式转换为 Deleter
6) 针对数组的特化行为与主模板相同,但仅在满足以下所有条件时才会参与重载决议:
  • U 是数组类型,
  • pointer element_type* 类型相同,
  • unique_ptr < U,E > :: pointer unique_ptr < U,E > :: element_type * 类型相同,
  • unique_ptr < U,E > :: element_type ( * ) [ ] 可转换为 element_type(*)[]
  • Deleter 是引用类型且 E Deleter 类型相同,或 Deleter 不是引用类型且 E 可隐式转换为 Deleter
7) 复制构造函数被显式删除。
8) 构造一个 unique_ptr ,其中存储的指针通过 u.release() 初始化,存储的删除器进行值初始化。此构造函数仅在 U* 可隐式转换为 T* Deleter std:: default_delete < T > 类型相同时参与重载决议。

目录

参数

p - 指向需管理对象的指针
d1, d2 - 用于销毁对象的删除器
u - 用于获取所有权的另一智能指针

注释

相较于结合使用 new 和重载版本 (2) ,通常更推荐使用 std::make_unique<T>

(since C++14)

std:: unique_ptr < Derived > 可通过重载 (6) 隐式转换为 std:: unique_ptr < Base > (因为被管理的指针和 std::default_delete 均可隐式转换)。

由于默认构造函数是 constexpr ,静态 unique_ptr 会在 静态非局部初始化 阶段完成初始化,早于任何动态非局部初始化的开始。这使得在任何静态对象的构造函数中使用 unique_ptr 都是安全的。

不存在从指针类型进行的 类模板实参推导 ,因为无法区分通过数组形式和非数组形式的 new 获得的指针。

(since C++17)

示例

#include <iostream>
#include <memory>
struct Foo // 要管理的对象
{
    Foo() { std::cout << "Foo ctor\n"; }
    Foo(const Foo&) { std::cout << "Foo copy ctor\n"; }
    Foo(Foo&&) { std::cout << "Foo move ctor\n"; }
    ~Foo() { std::cout << "~Foo dtor\n"; }
};
struct D // 删除器
{
    D() {};
    D(const D&) { std::cout << "D copy ctor\n"; }
    D(D&) { std::cout << "D non-const copy ctor\n"; }
    D(D&&) { std::cout << "D move ctor \n"; }
    void operator()(Foo* p) const
    {
        std::cout << "D is deleting a Foo\n";
        delete p;
    };
};
int main()
{
    std::cout << "Example constructor(1)...\n";
    std::unique_ptr<Foo> up1; // up1 为空
    std::unique_ptr<Foo> up1b(nullptr); // up1b 为空
    std::cout << "Example constructor(2)...\n";
    {
        std::unique_ptr<Foo> up2(new Foo); // up2 现在拥有一个 Foo
    } // Foo 被删除
    std::cout << "Example constructor(3)...\n";
    D d;
    {   // 删除器类型不是引用
        std::unique_ptr<Foo, D> up3(new Foo, d); // 删除器被复制
    }
    {   // 删除器类型是引用
        std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b 持有对 d 的引用
    }
    std::cout << "Example constructor(4)...\n";
    {   // 删除器不是引用
        std::unique_ptr<Foo, D> up4(new Foo, D()); // 删除器被移动
    }
    std::cout << "Example constructor(5)...\n";
    {
        std::unique_ptr<Foo> up5a(new Foo);
        std::unique_ptr<Foo> up5b(std::move(up5a)); // 所有权转移
    }
    std::cout << "Example constructor(6)...\n";
    {
        std::unique_ptr<Foo, D> up6a(new Foo, d); // D 被复制
        std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D 被移动
        std::unique_ptr<Foo, D&> up6c(new Foo, d); // D 是引用
        std::unique_ptr<Foo, D> up6d(std::move(up6c)); // D 被复制
    }
#if (__cplusplus < 201703L)
    std::cout << "Example constructor(7)...\n";
    {
        std::auto_ptr<Foo> up7a(new Foo);
        std::unique_ptr<Foo> up7b(std::move(up7a)); // 所有权转移
    }
#endif
    std::cout << "Example array constructor...\n";
    {
        std::unique_ptr<Foo[]> up<span

缺陷报告

下列行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 应用于 发布时的行为 正确行为
LWG 2118 C++11 unique_ptr<T[]> 的构造函数拒绝限定转换 接受限定转换
LWG 2520 C++11 unique_ptr<T[]> 意外地无法从 nullptr_t 构造 改为可构造
LWG 2801 C++11 默认构造函数未受约束 添加约束
LWG 2899 C++11 移动构造函数未受约束 添加约束
LWG 2905 C++11 从指针和删除器构造的约束条件有误 修正约束条件
LWG 2944 C++11 LWG 2905意外删除了某些前置条件 恢复前置条件