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
,这些指针指向需要管理的对象。
|
为便于下文描述,当满足以下任一条件时,称指针类型
|
(since C++17) |
shared_ptr
,即空
shared_ptr
。
shared_ptr
。
|
对于
(3,4,6)
,
|
(C++17 前) |
|
若
|
(C++17 起) |
T
不是数组类型);
delete
[
]
ptr
(若
T
是数组类型)
(C++17 起)
作为删除器。
Y
必须是完整类型。该 delete 表达式必须格式正确、具有明确定义的行为且不抛出任何异常。
此构造函数额外不参与重载决议,若 delete 表达式格式不正确。
(C++17 起)
|
|
(C++17 前) |
|
如果表达式 d ( ptr ) 格式不正确,或如果 std:: is_move_constructible_v < D > 为 false ,则这些构造函数额外不参与重载决议。 |
(C++17 起) |
shared_ptr
。若此
shared_ptr
是组中最后一个离开作用域的,它将调用最初由
r
管理的对象所存储的删除器。然而,对此
shared_ptr
调用
get()
将始终返回
ptr
的副本。程序员需确保在此 shared_ptr 存续期间
ptr
保持有效,例如在典型使用场景中:
ptr
是由
r
管理的对象的成员,或是
r.get()
的别名(如下行转换)
对于接受右值的第二个重载,调用后
r
为空且
r.
get
(
)
==
nullptr
。
(C++20 起)
shared_ptr
。若
r
未管理任何对象,则
*
this
亦不管理任何对象。当
Y*
不能
隐式转换为
(C++17 前)
兼容
(C++17 起)
T*
时,该模板重载不参与重载决议。
shared_ptr
。构造完成后,
*
this
包含
r
先前状态的副本,
r
变为空且其存储的指针为 null。若
Y*
不能
隐式转换为
(C++17 前)
与
(C++17 起)
T*
兼容,则该模板重载不参与重载决议。
shared_ptr
。
Y*
必须可隐式转换为
T*
。
(C++17 前)
此重载仅在
Y*
与
T*
兼容时参与重载决议。
(C++17 起)
注意
r.
lock
(
)
可用于相同目的:区别在于当参数为空时,该构造函数会抛出异常,而
std::
weak_ptr
<
T
>
::
lock
(
)
在这种情况下会构造一个空的
std::shared_ptr
。
shared_ptr
。
Y*
必须可转换为
T*
。构造完成后,
r
变为空。
shared_ptr
。与
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
,否则调用
delete
[
]
ptr
(C++17 起)
。
注释
构造函数通过类型为
U*
的指针
ptr
启用
shared_from_this
意味着:它会判断
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
(例如通过
shared_ptr
(
ptr.
get
(
)
)
),即使该对象继承自
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++11)
|
允许对象创建指向自身的
shared_ptr
(类模板) |