std::unique_ptr<T,Deleter>::unique_ptr
来自 cppreference.cn
< cpp | 内存 | unique ptr
| 主模板 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, /* 见下文 */ d1 ) noexcept; |
(3) | (C++23 起为 constexpr) |
unique_ptr( pointer p, /* 见下文 */ 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, /* 见下文 */ d1 ) noexcept; |
(3) | (C++23 起为 constexpr) |
template< class U > unique_ptr( U p, /* 见下文 */ 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 是 DefaultConstructible 且构造不抛出异常。这些重载仅当 std::is_default_constructible<Deleter>::value 为 true 且 Deleter 不是指针类型时参与重载决议。2) 构造一个拥有 p 的
std::unique_ptr,用 p 初始化存储的指针并值初始化存储的删除器。要求 Deleter 是 DefaultConstructible 且构造不抛出异常。此重载仅当 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 是 nothrow-CopyConstructible) |
| unique_ptr(pointer p, A&& d) noexcept; |
(2) | (要求 Deleter 是 nothrow-MoveConstructible) |
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,并在 u 中存储空指针来构造一个
unique_ptr。此构造函数仅当 std::is_move_constructible<Deleter>::value 为 true 时才参与重载决议。如果 Deleter 不是引用类型,则要求它是 nothrow-MoveConstructible(如果 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 | - | 另一个智能指针,从中获取所有权 |
[编辑] 注解
|
除了使用重载 (2) 和 new 之外,通常更好的做法是使用 std::make_unique<T>。 |
(C++14 起) |
std::unique_ptr<Derived> 可通过重载 (6) 隐式转换为 std::unique_ptr<Base>(因为管理的指针和 std::default_delete 都可隐式转换)。
由于默认构造函数是 constexpr,静态 unique_ptrs 在 静态非局部初始化 部分进行初始化,早于任何动态非局部初始化。这使得在任何静态对象的构造函数中使用 unique_ptr 都是安全的。
|
不支持从指针类型进行 类模板实参推导,因为无法区分从数组和非数组形式的 new 获取的指针。 |
(C++17 起) |
[编辑] 示例
运行此代码
#include <iostream> #include <memory> struct Foo // object to manage { 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 // deleter { 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 is empty std::unique_ptr<Foo> up1b(nullptr); // up1b is empty std::cout << "Example constructor(2)...\n"; { std::unique_ptr<Foo> up2(new Foo); //up2 now owns a Foo } // Foo deleted std::cout << "Example constructor(3)...\n"; D d; { // deleter type is not a reference std::unique_ptr<Foo, D> up3(new Foo, d); // deleter copied } { // deleter type is a reference std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b holds a reference to d } std::cout << "Example constructor(4)...\n"; { // deleter is not a reference std::unique_ptr<Foo, D> up4(new Foo, D()); // deleter moved } std::cout << "Example constructor(5)...\n"; { std::unique_ptr<Foo> up5a(new Foo); std::unique_ptr<Foo> up5b(std::move(up5a)); // ownership transfer } std::cout << "Example constructor(6)...\n"; { std::unique_ptr<Foo, D> up6a(new Foo, d); // D is copied std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D is moved std::unique_ptr<Foo, D&> up6c(new Foo, d); // D is a reference std::unique_ptr<Foo, D> up6d(std::move(up6c)); // D is copied } #if (__cplusplus < 201703L) std::cout << "Example constructor(7)...\n"; { std::auto_ptr<Foo> up7a(new Foo); std::unique_ptr<Foo> up7b(std::move(up7a)); // ownership transfer } #endif std::cout << "Example array constructor...\n"; { std::unique_ptr<Foo[]> up(new Foo[3]); } // three Foo objects deleted }
输出
Example constructor(1)... Example constructor(2)... Foo ctor ~Foo dtor Example constructor(3)... Foo ctor D copy ctor D is deleting a Foo ~Foo dtor Foo ctor D is deleting a Foo ~Foo dtor Example constructor(4)... Foo ctor D move ctor D is deleting a Foo ~Foo dtor Example constructor(5)... Foo ctor ~Foo dtor Example constructor(6)... Foo ctor D copy ctor D move ctor Foo ctor D non-const copy ctor D is deleting a Foo ~Foo dtor D is deleting a Foo ~Foo dtor Example constructor(7)... Foo ctor ~Foo dtor Example array constructor... Foo ctor Foo ctor Foo ctor ~Foo dtor ~Foo dtor ~Foo dtor
[编辑] 缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 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 意外删除。 | 已恢复。 |