c++11——share_ptr的助手weak_ptr

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一.weak_ptr简介

  • weak_ptr 是 C++ 标准库中的一个智能指针类,它是 share_ptr 的一个辅助类,用于实现弱引用,从而避免循环引用和内存泄漏等问题。

  • weak_ptr 的设计目的是为了实现对对象的弱引用,即不阻止对象被销毁,也不保证对象的生命周期。它通过使用 weak_ptr 指针来跟踪对象的生命周期,当对象被销毁时,weak_ptr 会自动释放所占用的资源。

  • weak_ptr 的主要用途是实现弱引用,从而避免循环引用和内存泄漏等问题。在某些情况下,例如多线程编程中,使用 weak_ptr 可以避免因为循环引用而导致的死锁问题。

  • weak_ptr 的使用方法与 share_ptr 类似,但是它不能直接使用 * 和 -> 操作符来访问对象,需要使用 lock() 方法来获取一个 share_ptr 指针,从而访问对象。

  • 成员函数use_count() 观测资源引用计数

  • 成员函数expired() 功能相当于 use_count()==0 表示被观测的资源(也就是shared_ptr的管理的资源)是否被销毁

  • 成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象, 进而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr

  • std: :weak_ptr 一般者是通过 std: : shared _ptr 来创建的

与share_ptr的区别

  • shared_ptr 用于管理对象的生命周期,而 weak_ptr 用于观察对象的生命周期
  • weak_ptr不会改变资源的引用计数,只是一个观察者的角色,通过观察shared_ptr来判定资源是否存在
  • weak_ptr持有的引用计数,不是资源的引用计数,而是同一个资源的观察者的计数
  • weak_ptr没有提供常用的指针操作,无法直接访问资源,需要先通过lock方法提升为shared_ptr强智能指针,才能访问资源

二.解决场景

1.循环引用

错误场景

循环引用是指两个或多个对象相互引用对方,导致它们之间的引用关系无法解除,从而导致内存泄漏等问题。

在 C++ 中,循环引用通常是由于使用 share_ptrweak_ptr 等智能指针类时,没有正确处理对象之间的引用关系导致的。例如,下面的代码就创建了一个循环引用:

#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() {
        std::cout << "Constructor called." << std::endl;
    }
    ~MyClass() {
        std::cout << "Destructor called." << std::endl;
    }
    std::shared_ptr<MyClass> ptr;
};

int main() {
    std::shared_ptr<MyClass> sp1(new MyClass);
    std::shared_ptr<MyClass> sp2(new MyClass);
    sp1->ptr = sp2;
    sp2->ptr = sp1;
    return 0;
}

在这个例子中,我们创建了两个 MyClass 的对象 sp1sp2,并将它们相互引用。
main 函数结束时,sp1sp2 的引用计数都为 1,因此它们都无法被销毁,从而导致循环引用。

解决问题

#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() {
        std::cout << "Constructor called." << std::endl;
    }
    ~MyClass() {
        std::cout << "Destructor called." << std::endl;
    }
    std::weak_ptr<MyClass> ptr;
};

int main() {
    std::shared_ptr<MyClass> sp1(new MyClass);
    std::shared_ptr<MyClass> sp2(new MyClass);
    sp1->ptr = sp2;
    sp2->ptr = sp1;
    return 0;
}

在这个例子中,我们创建了两个 MyClass 的对象 sp1sp2,并将它们相互引用。但是,我们使用 std::weak_ptr<MyClass> ,不会影响sp1sp2的强引用计数,当 main 函数结束时,sp1sp2 的引用计数都为 0,因此它们都被销毁,从而避免了循环引用。

2.观察者功能

#include <iostream>
#include <memory>
 
class MyClass {
public:
    MyClass() { std::cout << "MyClass Constructor" << std::endl; }
    ~MyClass() { std::cout << "MyClass Destructor" << std::endl; }
    void display() const { std::cout << "Displaying MyClass" << std::endl; }
};
 
int main() {
    std::shared_ptr<MyClass> sp = std::make_shared<MyClass>();
    std::weak_ptr<MyClass> wp = sp; // 创建weak_ptr
 
    // 检查weak_ptr是否有效
    if (auto temp_sp = wp.lock()) {
        temp_sp->display();
    } else {
        std::cout << "The object has been destroyed." << std::endl;
    }
 
    sp.reset(); // 释放shared_ptr,MyClass对象被销毁
 
    // 再次检查weak_ptr是否有效
    if (auto temp_sp = wp.lock()) {
        temp_sp->display();
    } else {
        std::cout << "The object has been destroyed." << std::endl;
    }
 
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值