std::shared_ptr<T>::shared_ptr
constexpr shared_ptr() noexcept; |
(1) | |
constexpr shared_ptr( std::nullptr_t ) noexcept; |
(2) | |
template< class Y > explicit shared_ptr( Y* ptr ); |
(3) | |
template< class Y, class Deleter > shared_ptr( Y* ptr, Deleter d ); |
(4) | |
template< class Deleter > shared_ptr( std::nullptr_t ptr, Deleter d ); |
(5) | |
template< class Y, class Deleter, class Alloc > shared_ptr( Y* ptr, Deleter d, Alloc alloc ); |
(6) | |
template< class Deleter, class Alloc > shared_ptr( std::nullptr_t ptr, Deleter d, Alloc alloc ); |
(7) | |
template< class Y > shared_ptr( const shared_ptr<Y>& r, element_type* ptr ) noexcept; |
(8) | |
template< class Y > shared_ptr( shared_ptr<Y>&& r, element_type* ptr ) noexcept; |
(8) | (C++20 起) |
shared_ptr( const shared_ptr& r ) noexcept; |
(9) | |
template< class Y > shared_ptr( const shared_ptr<Y>& r ) noexcept; |
(9) | |
shared_ptr( shared_ptr&& r ) noexcept; |
(10) | |
template< class Y > shared_ptr( shared_ptr<Y>&& r ) noexcept; |
(10) | |
template< class Y > explicit shared_ptr( const std::weak_ptr<Y>& r ); |
(11) | |
template< class Y > shared_ptr( std::auto_ptr<Y>&& r ); |
(12) | (C++17 中移除) |
template< class Y, class Deleter > shared_ptr( std::unique_ptr<Y,Deleter>&& r ); |
(13) | |
从指代要管理的对象的各种指针类型构造新的 shared_ptr
。
为以下描述的目的,若指针类型 |
(C++17 起) |
shared_ptr
,即空 shared_ptr
。shared_ptr
,管理 ptr
所指向的对象。
对于 (3-4,6) , |
(C++17 前) |
若 |
(C++17 起) |
T
不是数组类型;以 delete[] ptr 为删除器,若 T
是数组类型 (C++17 起)。 Y
必须是完整类型。 delete 表达式必须为良构,拥有良好定义行为且不抛异常。若 delete 表达式不为良构,则此构造函数不参与重载决议。 (C++17 起)d
为删除器。表达式 d(ptr) 表达式必须为良构,拥有良好定义行为且不抛异常。 d
的构造和从 d
构造存储的删除器必须不抛异常。
|
(C++17 前) |
若表达式 d(ptr) 非良构,或若 std::is_move_constructible<D>::value 为 false ,则这些构造函数不额外参与重载决议。 |
(C++17 起) |
shared_ptr
,与 r
的初始值共享所有权信息,但保有无关且不管理的指针 ptr
。若此 shared_ptr
是离开作用域的组中的最后者,则它将调用最初 r
所管理对象的析构函数。然而,在此 shared_ptr
上调用 get()
将始终返回 ptr
的副本。程序员负责确保只要此 shared_ptr
存在,此 ptr
就保持合法,例如在典型使用情况中,其中 ptr
是 r
所管理对象的成员,或是 r.get()
的别名(例如向下转型)。对于接收右值的第二重载,调用后 r
为空且 r.get() == nullptr 。 (C++20 起)shared_ptr
,共享 r
所管理对象的所有权。若 r
不管理对象,则 *this
亦不管理对象。若 Y*
不可隐式转换为 (C++17 前)兼容 (C++17 起) T*
,则模板重载不参与重载决议。r
移动构造 shared_ptr
。构造后, *this 含 r
先前状态的副本,而 r
为空且其存储的指针为空。若 Y*
不可隐式转换为 (C++17 前)兼容 (C++17 起) T*
,则模板重载不参与重载决议。shared_ptr
,共享 r
所管理对象的所有权。 Y*
必须可隐式转换为 T*
。 (C++17 前)此重载只有在 Y*
兼容 T*
时才会参与重载决议。 (C++17 起)注意可为相同目的用 r.lock() :区别是若参数为空则此构造函数抛异常,而 std::weak_ptr<T>::lock() 在该情况下构造空的 std::shared_ptr
。shared_ptr
,存储并占有 r
先前占有的对象。 Y*
必须可转换为 T*
。构造后, r
为空。shared_ptr
,管理当前为 r
所管理的对象。存储与 r
关联的删除器以在未来删除被管理对象。调用后 r
不管理对象。 若 std::unique_ptr<Y, Deleter>::pointer 不兼容 T* 则此重载不参与重载决议。若 r.get() 是空指针,则此重载等价于默认构造函数 (1) 。 |
(C++17 起) |
Deleter
是引用类型,则等价于 shared_ptr(r.release(), std::ref(r.get_deleter()) 。否则,等价于 shared_ptr(r.release(), std::move(r.get_deleter())) 。T
不是数组类型时,重载 (3) 、 (4) 及 (6) 以 ptr
启用 shared_from_this
,而重载 (13) 以 r.release() 所返回的指针启用 shared_from_this
。
注解
构造函数以 U*
类型指针 ptr
启用 shared_from_this
,表示它确定 U
是否拥有作为 std::enable_shared_from_this 特化的无歧义且可访问 (C++17 起)基类,而若如此,则构造函数求值该语句:
if (ptr != nullptr && ptr->weak_this.expired()) ptr->weak_this = std::shared_ptr<std::remove_cv_t<U>>(*this, const_cast<std::remove_cv_t<U>*>(ptr));
其中 weak_this
是 std::shared_from_this 的隐藏 mutable std::weak_ptr
成员。对 weak_this
成员的赋值不是原子的,且与任何到同一对象的潜在并发访问冲突。这确保将来对 shared_from_this() 调用,将与此裸指针构造函数所创建的 shared_ptr
共享所有权。
上述解释代码中,测试 ptr->weak_this.expired()
是为确保若 weak_this
指示已有占有者则无须重赋值它。从 C++17 起要求此测试。
裸指针重载认定被指向对象的所有权。从而,用裸指针重载为已经为 shared_ptr
所管理对象构造 shared_ptr
,例如以 shared_ptr(ptr.get()) 很可能导致未定义行为,即使对象有导出自 std::enable_shared_from_this 的类型。
因为默认构造函数是 constexpr
,静态 shared_ptrs 作为静态非局部初始化的一部分初始化,在任何动态初始化开始前。这使得在任何静态对象的构造函数中使用 shared_ptr 是安全的。
C++11 和 C++14 中,从 std::unique_ptr<T[]> 构造 std::shared_ptr<T> 是合法的:
std::unique_ptr<int[]> arr(new int[1]); std::shared_ptr<int> ptr(std::move(arr));
因为 shared_ptr
从 unique_ptr
获得其删除器( std::default_delete<T[]> 对象),故能正确解分配数组。
C++17 中这不再受允许。应当使用替代的数组形式 std::shared_ptr<T[]> 。
参数
ptr | - | 指向要管理的对象的指针 |
d | - | 用于销毁对象的删除器 |
alloc | - | 用于分配内部使用的数据的分配器 |
r | - | 要共享所有权或从它获得所有权的另一智能指针 |
异常
T
非数组类型,否则调用 delete[] ptr (C++17 起) 。示例
#include <memory> #include <iostream> struct Foo { Foo() { std::cout << "Foo...\n"; } ~Foo() { std::cout << "~Foo...\n"; } }; struct D { void operator()(Foo* p) const { std::cout << "Call delete from function object...\n"; delete p; } }; int main() { { std::cout << "constructor with no managed object\n"; std::shared_ptr<Foo> sh1; } { std::cout << "constructor with object\n"; std::shared_ptr<Foo> sh2(new Foo); std::shared_ptr<Foo> sh3(sh2); std::cout << sh2.use_count() << '\n'; std::cout << sh3.use_count() << '\n'; } { std::cout << "constructor with object and deleter\n"; std::shared_ptr<Foo> sh4(new Foo, D()); std::shared_ptr<Foo> sh5(new Foo, [](auto p) { std::cout << "Call delete from lambda...\n"; delete p; }); } }
输出:
constructor with no managed object constructor with object Foo... 2 2 ~Foo... constructor with object and deleter Foo... Foo... Call delete from lambda... ~Foo... Call delete from function object... ~Foo..
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 3548 | C++11 | 源自 unique_ptr 的构造函数复制构造删除器
|
改为移动构造 |
参阅
创建管理一个新对象的共享指针 (函数模板) | |
创建管理一个用分配器分配的新对象的共享指针 (函数模板) | |
(C++11) |
允许对象创建指代自身的 shared_ptr (类模板) |