【C++11】weak_ptr

目的

  1. weak_ptr只负责监测shared_ptr的内存资源,不参与管理,因此不会增加引用计数
  2. weak_ptr处理shared_ptr中因使用不当造成的内存泄漏问题
    a. 同一原始地址不能初始化多个共享智能指针
    b. 函数不能返回管理了this的共享智能指针对象
    c. 共享智能指针不能嵌套循环引用

表示方式

  1. 弱指针初始化
shared_ptr<int> sp(new int(22));
weak_ptr<int> wp1;
weak_ptr<int> wp2(wp1);//通过弱指针初始化
weak_ptr<int> wp3(sp);//通过共享指针初始化
weak_ptr<int> wp4;
wp4 = wp3;//通过弱指针赋值
weak_ptr<int> wp5;
wp5 = sp;//通过共享指针赋值
  1. 弱指针成员函数
//查看监测内存资源的引用计数
wp1.use_count() 
//弱智能指针判断资源是否已释放expired(),返回的是bool类型
cout << "weak " << (weak.expired() ? "is" : "is not") << " expired" << endl;
//获取监测资源的共享智能指针lock()
shared_ptr<int> sp1 = wp.lock();//赋值给sp2
//reset()重置
wp.reset()

细节

  1. 同一原始地址初始化多个共享智能指针,并不会增加引用计数,而是每个shared_ptr各自独立,因此会出现同一块地址两次析构的情况
  2. 函数不能返回管理了this的共享智能指针对象:本质也是同一块地址出现两次析构的情况。解决该问题需要先继承enable_shared_from_this模板类,再调用shared_from_this()方法。解决问题的本质是用weak_ptr的lock()方法来初始化新的shared_ptr
  3. 共享智能指针不能出现嵌套的循环引用:是使用weak_ptr解开共享智能指针中的嵌套循环

举例

weak_ptr初始化和使用 + shared_ptr存在的问题

//shared_ptr存在的问题
//1.存的是this指针的地址,this指针会被析构两次
//2.循环引用,形成环状结构导致引用计数无法减为0
#include <bits/stdc++.h>
using namespace std;
class Test{
public:
    Test(){}
    ~Test(){
        cout << "Test is destroyed..." << endl;
    }
    //需求,返回共享智能指针对象
    shared_ptr<Test> getSharedPtr(){
        return shared_ptr<Test>(this);
    }
};
//循环引用举例
class TA;
class TB;
class TA{
public:
    // shared_ptr<TB> bptr;
    weak_ptr<TB> bptr;//通过weak_ptr将闭环打开,修改TA或TB其中一个的就能将闭环打开
    ~TA(){
        cout << "TA is distroyed..." << endl;
    }
};
class TB{
public:
    // shared_ptr<TA> aptr;
    weak_ptr<TA> aptr;
    ~TB(){
        cout << "TB is distroyed..." << endl;
    }
};
int main(){
    cout << "-----------------弱智能指针的初始化---------------" << endl;
    shared_ptr<int> sp(new int(22));
    weak_ptr<int> wp1;
    weak_ptr<int> wp2(wp1);//通过弱指针初始化
    weak_ptr<int> wp3(sp);//通过共享指针初始化
    weak_ptr<int> wp4;
    wp4 = wp3;//通过弱指针赋值
    weak_ptr<int> wp5;
    wp5 = sp;//通过共享指针赋值

    cout << "----------------弱智能指针查看引用计数use_count:--------------" << endl;
    //通过打印的结果可以知道,weak_ptr只是监测资源,并不管理资源
    cout << "wp1: " << wp1.use_count() << endl;
    cout << "wp2: " << wp2.use_count() << endl;
    cout << "wp3: " << wp3.use_count() << endl;
    cout << "wp4: " << wp4.use_count() << endl;
    cout << "wp5: " << wp5.use_count() << endl;

    cout << "----------------弱智能指针判断资源是否已释放expired()和reset():--------------" << endl;
    //expired()返回的是bool类型
    shared_ptr<int> shared(new int(10));
    weak_ptr<int> weak(shared);
    cout << "1. weak " << (weak.expired() ? "is" : "is not") << " expired" << endl;
    shared.reset();
    cout << "2. weak " << (weak.expired() ? "is" : "is not") << " expired" << endl;

    cout << "----------------获取监测资源的共享智能指针lock():--------------" << endl;
    //wp.lock()获取到的是shared_ptr对象(内存地址+内存地址的值),但此时内存有由多个共享智能指针管理,wp.lock()获取到的内存地址是不变的
    shared_ptr<int> sp1, sp2, sp3;
    weak_ptr<int> wp;
    sp1 = std::make_shared<int>(520);
    wp = sp1;
    sp2 = wp.lock();//赋值给sp2
    cout << "use_count: " << wp.use_count() << endl;
    sp1.reset();//释放sp1
    cout << "use_count: " << wp.use_count() << endl;
    sp1 = wp.lock();//赋值给sp1
    cout << "use_count: " << wp.use_count() << endl;
    cout << "*sp1: " << *sp1 << endl;
    cout << "*sp2: " << *sp2 << endl;

    cout << "----------------share存在的问题:原始地址初始化多个共享智能指针--------------" << endl;
    Test* t = new Test;
    shared_ptr<Test> ptr1(t);
    // shared_ptr<Test> ptr2(t);//error:输出了两次析构,原因是由于同一个原始地址初始化了多个共享智能指针,会出现重复析构,因此只能通过ptr1初始化ptr2
    shared_ptr<Test> ptr2 = ptr1;

    cout << "----------------share存在的问题:函数不能返回管理了this的共享智能指针对象--------------" << endl;
    //error:本质还是同一个原始地址初始化了多个共享智能指针
    // shared_ptr<Test> thisptr1(new Test);
    // cout << "use_count:" << thisptr1.use_count() << endl;
    // shared_ptr<Test> thisptr2 = thisptr1->getSharedPtr();
    // cout << "use_count:" << thisptr1.use_count() << endl;

    cout << "----------------share存在的问题:共享智能指针不能循环引用--------------" << endl;
    // shared_ptr<TA> Aptr(new TA);
    // shared_ptr<TB> Bptr(new TB);
    // cout << "TA对象 use_count:" << Aptr.use_count() << endl;
    // cout << "TB对象 use_count:" << Bptr.use_count() << endl;

    // Aptr->bptr = Bptr;
    // Bptr->aptr = Aptr;
    // cout << "TA对象 use_count:" << Aptr.use_count() << endl;
    // cout << "TB对象 use_count:" << Bptr.use_count() << endl;
    //此时发现,未输出析构语句,说明内存没有释放,出现内存泄漏现象
    // system("pause");
    return 0;
}

weak_ptr解决share_ptr的问题

//shared_ptr存在的问题
//1.存的是this指针的地址,this指针会被析构两次
//2.循环引用,形成环状结构导致引用计数无法减为0
#include <bits/stdc++.h>
using namespace std;
class Test:public enable_shared_from_this<Test>{//继承enable_shared_from_this模板类,调用里面的shared_from_this()方法
public:
    Test(){}
    ~Test(){
        cout << "Test is destroyed..." << endl;
    }
    //需求,返回共享智能指针对象
    shared_ptr<Test> getSharedPtr(){
        // return shared_ptr<Test>(this);
        return shared_from_this();//解决返回this的共享智能指针,其内部是用weak_ptr.lock()实现
    }
};

//循环引用举例
class TA;
class TB;
class TA{
public:
    // shared_ptr<TB> bptr;
    weak_ptr<TB> bptr;//通过weak_ptr将闭环打开,修改TA或TB其中一个的就能将闭环打开
    ~TA(){
        cout << "TA is distroyed..." << endl;
    }
};
class TB{
public:
    // shared_ptr<TA> aptr;
    weak_ptr<TA> aptr;
    ~TB(){
        cout << "TB is distroyed..." << endl;
    }
};
int main(){
    cout << "----------------weak解决share:函数不能返回管理了this的共享智能指针对象--------------" << endl;
    // error:本质还是同一个原始地址初始化了多个共享智能指针,出现两次析构
    //需要继承enable_shared_from_this模板类,调用里面的shared_from_this()方法来解决
    #if 0
    shared_ptr<Test> thisptr1(new Test);//由于继承,此时会初始化父类中weak_ptr指向此时声明的shared_ptr
    cout << "use_count:" << thisptr1.use_count() << endl;
    shared_ptr<Test> thisptr2 = thisptr1->getSharedPtr();//返回的是weak_ptr检测的内存对应的shared_ptr
    cout << "use_count:" << thisptr1.use_count() << endl;
    #endif

    cout << "----------------weak解决share:共享智能指针不能出现嵌套的循环引用--------------" << endl;
    shared_ptr<TA> Aptr(new TA);
    shared_ptr<TB> Bptr(new TB);
    cout << "TA对象 use_count:" << Aptr.use_count() << endl;
    cout << "TB对象 use_count:" << Bptr.use_count() << endl;

    Aptr->bptr = Bptr;
    Bptr->aptr = Aptr;
    cout << "TA对象 use_count:" << Aptr.use_count() << endl;
    cout << "TB对象 use_count:" << Bptr.use_count() << endl;
    //此时发现,未输出析构语句,说明内存没有释放,出现内存泄漏现象
    //当修改为weak_ptr后,恢复正常,内存正常释放
    // system("pause");
    return 0;
}

运行结果

在这里插入图片描述
在这里插入图片描述

参考学习

https://www.bilibili.com/video/BV1bX4y1G7ks

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值