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。|
对于 (3,4,6), |
(C++17 前) |
|
如果 |
(C++17 起) |
T 不是数组类型;如果 T 是数组类型,则为 delete[] ptr(C++17 起) 作为删除器。Y 必须是一个完整类型。删除表达式必须格式良好,行为明确,且不抛出任何异常。如果删除表达式格式不良好,则此构造函数不参与重载决议。(C++17 起)|
|
(C++17 前) |
|
如果表达式 d(ptr) 格式不良好,或者如果 std::is_move_constructible_v<D> 为 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*,则模板重载不参与重载决议。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。
目录 |
[编辑] 参数
| ptr | - | 指向要管理的对象的指针 |
| d | - | 用于销毁对象的删除器 |
| alloc | - | 用于内部数据分配的分配器 |
| r | - | 另一个智能指针,用于共享所有权或从中获取所有权 |
[编辑] 异常
T 不是数组类型,否则调用 delete[] ptr(C++17 起)。[编辑] 注意
构造函数启用 shared_from_this,带一个类型为 U* 的指针 ptr,这意味着它确定 U 是否有一个明确且可访问的(C++17 起)基类是 std::enable_shared_from_this 的特化,如果是,则构造函数评估 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 的赋值不是原子的,并且与对同一对象的任何潜在并发访问冲突。这确保了未来对 shared_from_this() 的调用将与此原始指针构造函数创建的 std::shared_ptr 共享所有权。
上述代码中的测试 ptr->weak_this .expired() 确保如果 weak_this 已经指示了一个所有者,则不会重新赋值。此测试在 C++17 中是必需的。
原始指针重载假定指向对象的拥有权。因此,对于已经由 shared_ptr 管理的对象(例如通过 shared_ptr(ptr.get()))使用原始指针重载构造 shared_ptr 可能会导致未定义行为,即使对象类型派生自 std::enable_shared_from_this。
由于默认构造函数是 constexpr,静态 shared_ptr 作为静态非局部初始化的一部分进行初始化,在任何动态非局部初始化开始之前。这使得在任何静态对象的构造函数中使用 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 从 std::unique_ptr 获取其删除器(一个 std::default_delete<T[]> 对象),因此数组将正确地被释放。
在 C++17 中不再允许这样做。应该使用数组形式 std::shared_ptr<T[]>。
[编辑] 示例
#include <iostream> #include <memory> struct Foo { int id{0}; Foo(int i = 0) : id{i} { std::cout << "Foo::Foo(" << i << ")\n"; } ~Foo() { std::cout << "Foo::~Foo(), id=" << id << '\n'; } }; struct D { void operator()(Foo* p) const { std::cout << "Call delete from function object. Foo::id=" << p->id << '\n'; delete p; } }; int main() { { std::cout << "1) constructor with no managed object\n"; std::shared_ptr<Foo> sh1; } { std::cout << "2) constructor with object\n"; std::shared_ptr<Foo> sh2(new Foo{10}); std::cout << "sh2.use_count(): " << sh2.use_count() << '\n'; std::shared_ptr<Foo> sh3(sh2); std::cout << "sh2.use_count(): " << sh2.use_count() << '\n'; std::cout << "sh3.use_count(): " << sh3.use_count() << '\n'; } { std::cout << "3) constructor with object and deleter\n"; std::shared_ptr<Foo> sh4(new Foo{11}, D()); std::shared_ptr<Foo> sh5(new Foo{12}, [](auto p) { std::cout << "Call delete from lambda... p->id=" << p->id << '\n'; delete p; }); } }
输出
1) constructor with no managed object 2) constructor with object Foo::Foo(10) sh2.use_count(): 1 sh2.use_count(): 2 sh3.use_count(): 2 Foo::~Foo(), id=10 3) constructor with object and deleter Foo::Foo(11) Foo::Foo(12) Call delete from lambda... p->id=12 Foo::~Foo(), id=12 Call delete from function object. Foo::id=11 Foo::~Foo(), id=11
[编辑] 缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
|---|---|---|---|
| LWG 3548 | C++11 | 从 unique_ptr 构造函数复制构造删除器 |
改为移动构造 |
[编辑] 参阅
| (C++20 起) |
创建一个管理新对象的共享指针 (函数模板) |
| 创建一个共享指针,该指针管理使用分配器分配的新对象 (函数模板) | |
| (C++11) |
允许对象创建指向自身的 shared_ptr(类模板) |