共享指针 shared_ptr

目录

1. 共享指针的作用

2. 共享指针的声明

3. shared_from_this() 

4. 循环引用示例

1. 共享指针的作用

共享所管理的指针的内容的传播和释放,例如解决多线程使用同一个对象时的析构问题

使用场景示例:

对于同一帧视频数据

        业务A要将数据保存在本地

        业务B要将数据上传到云端

这时候如果将数据都深拷贝一份再传入各个业务线程,就会带来很大的资源浪费,此时就可以使用共享指针来管理指向这些数据的指针;

前提是要管理的这些数据,是只读的,如果要修改内容,就要考虑采用加锁等手段来避免产生数据安全的问题

2. 共享指针的声明

make_shared() 声明共享指针

reset() 重置共享指针

// 最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数
// 不用make_shared(),会单独为被管理对象和引用计数各分配一次内存
// 使用make_shared(),会一次分配一块足够大的内存
std::shared_ptr<int> sptr1 = std::make_shared<int>(10);
std::shared_ptr<int> sptr2(new int(20));

// 注意事项
// 不要使用一个裸指针初始化多个shared_ptr,会导致该指针被删除多次
int *ptr = new int(10); // 错误写法
std::shared_ptr<int> sptr(ptr);
std::shared_ptr<int> sptr1(ptr);

get() 获取原始指针

std::shared_ptr<int> sptr = std::make_shared<int>(10);
int *ptr = sptr.get();

// 注意事项
// get() 函数返回共享指针中管理的指针,但是要小心使用
delete ptr; // 会导致双重析构
// 如果共享指针的引用计数=0,释放了其管理的对象,此处的ptr就变成了空悬指针

use_count() 返回共享指针的引用计数

unique() 若use_count() == 1 返回true,否则返回false;

3. shared_from_this() 

返回由shared_ptr管理的对象的this指针

使用场景:

        一个类中,可能会有业务需求,需要定义一些方法来返回当前对象的this指针,如果直接返回一个this裸指针,而该类又被share_ptr所管理,this裸指针和shared_ptr其实是引用的同一个对象的内存,但是shared_ptr感知不到所返回的this裸指针,就会出现跟使用get()一样的问题,双重析构或空悬指针;

解决方案:shared_from_this() 和继承enable_shared_from_this类,搭配使用(固定写法)

#include<memory>

// 错误写法
class A {
    public:
        std::shared_ptr<A> GetSelf() {
            return std::shared_ptr<A>(this);
        }
};

// 正确写法
class A :public std::enable_shared_from_this<A>{
    public:
        std::shared_ptr<A> GetSelf() {
            return shared_from_this();
        }
};

int main(){
    std::shared_ptr<A> sp1(new A);
    std::shared_ptr<A> sp2 = sp1 -> GetSelf();
}

4. 循环引用示例

        两个共享指针循环引用,会导致这两个指针的引用计数永远都不会降到0,其管理的对象的析构函数永远都不会被调用,占用的内存就不会被释放,可能导致内存不足、程序崩溃、内存资源浪费、在资源受限的环境中,程序性能下降;

解决方案:使用weak_ptr替代其中一个类中的shared_ptr,因为weak_ptr不会增加对象的引用计数,因此可以防止循环引用

#include <iostream>
#include <memory>

class B;

class A {
public:
  std::shared_ptr<B> bsp;
  ~A() { std::cout << "A destructor" << std::endl; }
};

class B {
public:
  std::shared_ptr<A> asp;
  ~B() { std::cout << "B destructor" << std::endl; }
};

int main() {
  std::shared_ptr<A> asp = std::make_shared<A>();
  std::shared_ptr<B> bsp = std::make_shared<B>();
  asp->bsp = bsp;
  bsp->asp = asp;

  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值