当前位置: 首页 > news >正文

c++11——share_ptr的助手weak_ptr

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

文章目录

  • 一.weak_ptr简介
    • 与share_ptr的区别
  • 二.解决场景
    • 1.循环引用
      • 错误场景
      • 解决问题
    • 2.观察者功能


一.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;
}

在这里插入图片描述


http://www.mrgr.cn/news/25413.html

相关文章:

  • 前端 + 接口请求实现 vue 动态路由
  • buck boost Ldo 经典模型的默写
  • 排序题目:一手顺子
  • 【办公】会议纪要模板
  • OJ 两两交换链表中的节点
  • MySQL之库和表操作
  • Python容器一之字符串
  • 好看好听的小猪包扩音器,轻巧便携更好用,得胜E10上手
  • 批量插入insert到SQLServer数据库,BigDecimal精度丢失解决办法,不动代码,从驱动层面解决
  • 干部画像系统是什么?
  • 卫生间漏水原因很多,切莫病急乱投医
  • 直播电商平台如何合理分账给供应商/主播
  • 基于SpringBoot的准妈妈孕期交流平台
  • 开源模型应用落地-qwen2-7b-instruct-LoRA微调-unsloth(让微调起飞)-单机单卡-V100(十六)
  • Vue3使用Websocket进行跨页面通信
  • Vue路由的分类与使用
  • 缓存预热/雪崩/穿透/击穿
  • 牛客小白月赛99(下)
  • Shell脚本-拆分文件并重命名(性能测试)
  • 记一次幸运的漏洞挖掘