前面的文章已经提出了一个关键点,两个unique_ptr
智能指针之间无法进行值传递,但是明显很多时候需要多个指针管理同一个内存。这个时候shared_ptr
就应运而生了。
每种智能指针都是以类模板的方式实现的,shared_ptr
也不例外。shared_ptr<T>
(其中 T
表示指针指向的具体数据类型)的定义位于<memory>头文件,并位于 std 命名空间中。
所以需要在使用前包含:
#include <memory>
1、shared_ptr的初始化
a. 通过如下 2 种方式,可以构造出 shared_ptr 类型的空智能指针:
std::shared_ptr<int> p1; //不传入任何实参
std::shared_ptr<int> p2(nullptr); //传入空指针 nullptr
注意,空的 shared_ptr 指针,其初始引用计数为 0,而不是 1。
b. 在构建 shared_ptr 智能指针,也可以明确其指向。例如:
std::shared_ptr<int> p3(new int(10));
由此,我们就成功构建了一个 shared_ptr 智能指针,其指向一块存有 10 这个 int 类型数据的堆内存空间。
2、 推荐使用std::make_shared进行初始化
make_shared用起来更安全也更简单。
std::shared_ptr<int> p3 = std::make_shared<int>(10);
使用方法跟make_unique
基本一样,先跟上类型,然后后面括号里面加上初始化的参数。
3、shared_ptr之间的复制
shared_ptr 模板还提供有相应的拷贝构造函数和移动构造函数,例如:
//调用拷贝构造函数
std::shared_ptr<int> p4(p3);//或者 std::shared_ptr<int> p4 = p3;
//调用移动构造函数
std::shared_ptr<int> p5(std::move(p4)); //或者 std::shared_ptr<int> p5 = std::move(p4);
4、shared_ptr模板类提供的成员方法
成员方法名 | 功 能 |
---|---|
operator=() | 重载赋值号,使得同一类型的 shared_ptr 智能指针可以相互赋值。 |
operator()* | 重载 * 号,获取当前 shared_ptr 智能指针对象指向的数据。 |
operator->() | 重载 -> 号,当智能指针指向的数据类型为自定义的结构体时,通过 -> 运算符可以获取其内部的指定成员。 |
swap() | 交换 2 个相同类型 shared_ptr 智能指针的内容。 |
reset() | 当函数没有实参时,该函数会使当前 shared_ptr 所指堆内存的引用计数减 1,同时将当前对象重置为一个空指针;当为函数传递一个新申请的堆内存时,则调用该函数的 shared_ptr 对象会获得该存储空间的所有权,并且引用计数的初始值为 1。 |
get() | 获得 shared_ptr 对象内部包含的普通指针。 |
use_count() | 返回同当前 shared_ptr 对象(包括它)指向相同的所有 shared_ptr 对象的数量。 |
unique() | 判断当前 shared_ptr 对象指向的堆内存,是否不再有其它 shared_ptr 对象再指向它。 |
operator bool() | 判断当前 shared_ptr 对象是否为空智能指针,如果是空指针,返回 false;反之,返回 true。 |
std :: shared_ptr和数组
在C ++ 14和更早版本中,std :: shared_ptr没有适当的支持来管理数组,因此不应用于管理C样式的数组。从C ++ 17开始,std :: shared_ptr确实支持数组。但是,从C ++ 17开始,std :: make_shared仍缺乏对数组的适当支持,因此不应用于创建共享数组。这可能会在C ++ 20中解决。
std::shared_ptr<int> p7(new int[10]);