共享指针 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;
}

shared_ptrC++标准库(<memory> 头文件)中的一种智能指针,用于管理动态分配的内存。其原理、用法和应用场景如下: - **原理**:shared_ptr通过引用计数机制,跟踪有多少个shared_ptr实例共享同一块内存。当最后一个shared_ptr被销毁或重置时,引用计数变为0,内存自动释放。这种“共享所有权”的特性使其适用于多人共用资源的场景。在实际的C++开发中,智能指针shared_ptr主要功能是管理动态创建对象的销毁,从而帮助彻底消除内存泄漏和悬空指针的问题。例如,有些内存资源已被释放,但指向它的指针未改变指向(成为野指针)且后续还在使用;或有些内存资源已被释放,后期又试图再释放一次(重复释放同一块内存会导致程序运行崩溃);没有及时释放不再使用的内存资源,造成内存泄漏,程序占用的内存资源越来越多等问题,shared_ptr都能有效避免 [^1][^3]。 - **用法**:shared_ptr的用法跟unique_ptr类似,多了一些接口函数。get函数可获得该对象管理资源的指针,use_count函数可以查看共享资源的对象有几个。以下是一个使用示例: ```cpp #include <iostream> #include <memory> class Date { public: int _year; int _month; int _day; void Print() { std::cout << _year << "-" << _month << "-" << _day << std::endl; } }; void test_shared1() { std::shared_ptr<Date> sp1(new Date); sp1->_day = 5; std::shared_ptr<Date> sp2(sp1); sp2->_year = 2024; Date* ptr = sp1.get(); ptr->_month = 9; sp1->Print(); std::cout << "引用计数:" << sp1.use_count() << std::endl; } int main() { test_shared1(); return 0; } ``` 此外,std::make_shared比直接使用new更高效,因为它只分配一次内存 [^2][^4]。 - **应用场景**:shared_ptr适合多人共用资源的场景,在实际开发中,当多个部分需要访问同一块动态分配的内存,且需要确保在所有使用者都不再使用该内存时才释放它,就可以使用shared_ptr [^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值