智能指针之weak_ptr06

本文深入探讨了C++中weak_ptr的概念与用法,包括weak_ptr如何解决shared_ptr的循环引用问题,weak_ptr的初始化、lock()和expired()函数的使用等关键知识点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 weak_ptr

看名字就知道,他是一个弱引用,他的存在是为了辅助shared_ptr的循环引用问题,它不占用引用数。只能通过shared_ptr或者weak_ptr构造赋值。
它没有重载 * 和 -> 运算符,因此不可以直接通过 weak_ptr 访问对象,典型的用法是通过 lock() 成员函数来获得 shared_ptr,进而使用对象。
大家理解时,将weak_ptr看成用来监视shared_ptr(强引用)的生命周期用。是一种对shared_ptr的扩充。

1 weak_ptr初始化赋值

    //1 weak_ptr初始化赋值
    std::shared_ptr<int> sh = std::make_shared<int>();  // 默认值为0
    cout<<sh.use_count()<<endl;                         // 1
    std::weak_ptr<int> w(sh);                           // 用shared_ptr构造
    std::weak_ptr<int> w1(w);                           // 用weak_ptr构造
    cout<<sh.use_count()<<endl;                         // 1

    std::weak_ptr<int> w2=sh;                           // 用shared_ptr赋值
    std::weak_ptr<int> w3=w2;                           // 用weak_ptr赋值
    cout<<sh.use_count()<<endl;                         // 1

2 lock()函数

lock():检查weak_ptr所指向的对象是否存在,如果存在那么lock将返回一个指向该对象的shared_ptr(指向对象的强引用就会+1),如果指向对象不存在,lock会返回一个空的shared_ptr。通过lock可以将weak_ptr转化成shared_ptr使用。
例子看下面。

3 expired()函数

expired函数:判断weak_ptr的方法expired判断shared_ptr管理的资源是否已经释放。true已释放,0未释放。

4 上面1,2,3大点的案例

注释已经标明清楚。

//4 weak_ptr  --小弟
void test16(){

    //1 weak_ptr初始化赋值
    std::shared_ptr<int> sh = std::make_shared<int>();  // 默认值为0
    cout<<sh.use_count()<<endl;                         // 1
    std::weak_ptr<int> w(sh);                           // 用shared_ptr构造
    std::weak_ptr<int> w1(w);                           // 用weak_ptr构造
    cout<<sh.use_count()<<endl;                         // 1

    std::weak_ptr<int> w2=sh;                           // 用shared_ptr赋值
    std::weak_ptr<int> w3=w2;                           // 用weak_ptr赋值
    cout<<sh.use_count()<<endl;                         // 1

    /*
        2. lock函数:检查weak_ptr所指向的对象是否存在,
        如果存在那么lock将返回一个指向该对象的shared_ptr(指向对象的强引用就会+1),
        如果指向对象不存在,lock会返回一个空的shared_ptr.
        通过lock可以将weak_ptr转化成shared_ptr使用
    */
    std::shared_ptr<int> another = w2.lock();  
    if (another != nullptr){
        *another = 12;
        cout<<"sh管理的内存未被释放"<<endl;
    }
    cout<<sh.use_count()<<endl;                         // 2

    //3 expired函数:判断weak_ptr的方法expired判断shared_ptr管理的资源是否已经释放。true已释放,0未释放
    bool isDeleted = w2.expired();
    cout<<sh.use_count()<<endl;                         // 2
    cout<<isDeleted<<endl;                              // 0 因为程序还没结束 sh与another在引用 
    
    //测试lock为空时
    another.reset();//无参reset置空,该内存引用数减1,本对象another的引用计数为0
    sh.reset();
    if (w2.lock() == nullptr){
        cout<<"sh管理的内存被释放"<<endl;
    }
}

结果:
在这里插入图片描述

注意,在shared_ptr之前我们已经说过了reset的使用,这里再简单说明一下。
reset():将该引用的引用计数设置为空,不影响该片内存的引用计数,但是该片内存的引用计数会减少1。

5 尺寸问题

weak_ptr与shared_ptr的尺寸一样大,是裸指针的两倍。内部有两个裸指针。
在这里插入图片描述

  • 1)第一个裸指针指向的是这个智能指针所指向的对象。
  • 2)第二个所指针指向一个数据结构(控制块),这个控制块里有:
    1、引用计数(强引用计数、弱引用计数)
    2、其他数据(弱引用删除器,互斥锁等等)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值