std::unique_ptr<T,Deleter>::unique_ptr
声明
- 主模板,unique_ptr<T>
- 数组特化,unique_ptr<T[]>
- C++23
- C++17
- C++11
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
constexpr explicit unique_ptr( pointer p ) noexcept;
// 3)
constexpr unique_ptr( pointer p, /* see below */ d1 ) noexcept;
// 4)
constexpr unique_ptr( pointer p, /* see below */ d2 ) noexcept;
// 5)
constexpr unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
constexpr unique_ptr( unique_ptr<U, E>&& u ) noexcept;
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
explicit unique_ptr( pointer p ) noexcept;
// 3)
unique_ptr( pointer p, /* see below */ d1 ) noexcept;
// 4)
unique_ptr( pointer p, /* see below */ d2 ) noexcept;
// 5)
unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
explicit unique_ptr( pointer p ) noexcept;
// 3)
unique_ptr( pointer p, /* see below */ d1 ) noexcept;
// 4)
unique_ptr( pointer p, /* see below */ d2 ) noexcept;
// 5)
unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
// 7)
template< class U >
unique_ptr( std::auto_ptr<U>&& u ) noexcept;
- C++23
- C++11
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
template< class U >
constexpr explicit unique_ptr( U p ) noexcept;
// 3)
template< class U >
constexpr unique_ptr( U p, /* see below */ d1 ) noexcept;
// 4)
template< class U >
constexpr unique_ptr( U p, /* see below */ d2 ) noexcept;
// 5)
constexpr unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
constexpr unique_ptr( unique_ptr<U, E>&& u ) noexcept;
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
template< class U >
explicit unique_ptr( U p ) noexcept;
// 3)
template< class U >
unique_ptr( U p, /* see below */ d1 ) noexcept;
// 4)
template< class U >
unique_ptr( U p, /* see below */ d2 ) noexcept;
// 5)
unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
描述
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)
构造一个std::unique_ptr
对象,它拥有p
,用p
初始化存储的指针,并根据D
是否为引用类型来初始化删除器D
-
如果
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) -
如果
D
为左值引用类型A&
,则签名如下:unique_ptr(pointer p, A& d) noexcept; (1)
unique_ptr(pointer p, A&& d) = delete; (2) -
如果
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
与指针类型相同,或者U
为std::nullptr_t
,或者pointer
与element_type*
类型相同,并且U
为某种指针类型V*
,使得V(*)[]
可以隐式转换为element_type(*)[]
。
5)
构造一个unique_ptr
,通过将所有权从u
转移到*this
,并在u
中存储null
指针。此构造函数仅在std::is_move_constructible<Deleter>::value
为true
时才参与重载解析。如果Deleter
不是引用类型,则要求它是nothrow-MoveConstructible(如果Deleter
是引用,则在移动构造后get_deleter()
和u.get_deleter()
引用相同的值)
6)
构造一个unique_ptr
,通过将所有权从u
转移到*this
,其中u
使用指定的删除器(E)
进行构造。这取决于E
是否为引用类型,如下所示
- 如果
E
为引用类型,则此删除器从u
的删除器复制构造(要求此构造不抛出) - 如果
E
为非引用类型,则此删除器从u
的删除器移动构造(要求此构造不抛出)
此构造函数仅在以下所有条件为真时才参与重载解析
unique_ptr<U, E>::pointer
可以隐式转换为pointer
U
不是数组类型- 要么
Deleter
是引用类型且E
与D
类型相同,要么Deleter
不是引用类型且E
可以隐式转换为D
7)
构造一个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>
可以隐式转换为std::unique_ptr<Base>
,通过重载(6)(因为管理指针和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