16.3 C++智能指针-weak_ptr

2023-10-18 19:20
文章标签 c++ 指针 智能 weak ptr 16.3

本文主要是介绍16.3 C++智能指针-weak_ptr,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

16.1 C++智能指针-new/delete探秘
16.2 C++智能指针-shared_ptr
16.3 C++智能指针-weak_ptr
16.4 C++智能指针-shared_ptr使用场景、陷阱、性能分析与使用建议
16.5 C++智能指针-unique_ptr

文章目录

  • 3.weak_ptr
    •   3.1 weak_ptr简介
    •   3.2 weak_ptr常用操作
      • (1)use_count成员函数
      • (2)expired成员函数
      • (3)尺寸问题

    weak_ptr这个智能指针是用来辅助shared_ptr工作的。那么,现在就来介绍一下weak_ptr

3.weak_ptr

  3.1 weak_ptr简介

    weak_ptr是一个智能指针,也是一个类模板。这个智能指针指向一个由shared_ptr管理的对象,但是这种指针并不控制所指向的对象的生存期。换句话来说,将weak_ptr绑定到shared_ptr上并不会改变shared_ptr的引用计数(更确切地说,weak_ptr的构造和析构不会增加或者减少所指向对象的引用计数)。当shared_ptr需要释放所指向的对象时照常释放,不管是否有weak_ptr指向该对象。这就是weak“弱”的原因——能力弱(弱共享/弱引用:共享其他的shared_ptr所指向的对象),控制不了所指向对象的生存期
    创建weak_ptr的时候,一般是用一个make_shared来初始化
    前面谈到的shared_ptr指向的对象代表的引用统统指的都是强引用,而weak_ptr所指向的对象代表的引用统统都是弱引用
    weak_ptr所指向的对象有可能会不存在,所以,程序员是不能使用weak_ptr来直接访问对象的,必须要使用一个叫作lock的成员函数,lock的功能就是检查weak_ptr所指向的对象是否还存在,如果存在,lock能够返回一个指向共享对象的shared_ptr(当然原shared_ptr引用计数会+1),如果不存在,则返回一个空的shared_ptr。

{auto pi = make_shared<int>(100);weak_ptr<int> piw(pi); //piw弱共享pi,pi引用计数(强引用计数)不改变,弱引用计数字会从0变成1;pi和piw两者指向相同位置//weak_ptr<int> piw;piw = pi; //pi这里是一个shared_ptr,赋值给一个weak_ptr。pi和piw两者指向相同位置weak_ptr<int> piw2;piw2 = piw; //把weak_ptr赋给另外一个weak_ptr,现在pi是1个强引用,2个弱引用auto pi2 = piw.lock(); //强引用(shared_ptr)计数会加1,现在pi是2个强引用,2个弱引用if (pi2 != nullptr)    //条件成立;写成if(pi2)也可以{			cout << "所指对象存在" << endl;}		
}

在这里插入图片描述

{auto pi = make_shared<int>(100);weak_ptr<int> piw(pi); //piw弱共享pi,pi强引用计数不改变,弱引用计数字会从0变成1pi.reset();            //因为pi是唯一指向该对象的指针,则释放pi指向的对象,将pi置空auto pi2 = piw.lock(); //因为所指向的对象被释放了,所以piw弱引用也属于“过期”的了if (pi2 != nullptr)    //条件不再成立{cout << "所指对象存在" << endl;}
}

在这里插入图片描述

  3.2 weak_ptr常用操作

(1)use_count成员函数

    获取与该弱指针共享对象的其他shared_ptr的数量,或者说获得当前所观测资源的引用计数(强引用计数)

(2)expired成员函数

    是否过期的意思,若该指针的use_cout为0(表示该弱指针所指向的对象已经不存在),则返回true,否则返回false。换句话说,判断所观测的对象(资源)是否已经被释放。

{auto pi = make_shared<int>(100);auto pi2(pi); //pi2类型是个shared_ptrweak_ptr<int> piw(pi);int isc = piw.use_count(); //2:与本piw共享对象的shared_ptr数量pi.reset();pi2.reset();if (piw.expired()) //是否过期,此时成立{cout << "piw已过期" << endl;}		
}
{auto p1 = make_shared<int>(42);weak_ptr<int> pw;pw = p1;    //可以用shared_ptr给weak_ptr值,现在p1是1个强引用,1个弱引用if (!pw.expired()) //条件成立{//没过期:auto p2 = pw.lock(); //返回的p2是一个shared_ptr,现在p1是2个强引用,1个弱引用			if (p2 != nullptr)//条件成立{cout << "所指对象存在" << endl;}//离开这个范围,p1的强引用计数恢复为1,弱引用保持为1}else{cout << "pw已经过期" << endl;}//走到这里,p1是1个强引用,1个弱引用		
}
{weak_ptr<int> pw;{auto p1 = make_shared<int>(42);pw = p1; //可以用shared_ptr给weak_ptr值} //离开这里时p1就失效了,那么pw会变成啥情况?//这里pw这个weak_ptr就会过期了if (pw.expired()) //条件成立{cout << "pw已经过期" << endl;}		
}

在这里插入图片描述

(3)尺寸问题

    其实weak_ptr尺寸(就是大小或者sizeof)和shared_ptr对象尺寸一样大,后续章节里会提到shared_ptr的尺寸问题,这里先提一下weak_ptr对象尺寸问题。

{shared_ptr<int> p1(new int(100));weak_ptr<int> pw(p1);int ilen = sizeof(p1);  //8int ilen2 = sizeof(pw); //8cout << "设置断点" << endl;
}

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

    在当前Visual Studio的x86平台下,一个裸指针的sizeof值是4字节。从上面代码可以看到,weak_ptr或shared_ptr的尺寸都是8字节,其实,这8字节中包含了两个裸指针
可以看到:
(1)第一个裸指针指向的是该智能指针所指向的对象。
(2)第二个裸指针指向一个很大的数据结构(控制块)。这个控制块里面有:
    所指对象的引用计数。
    所指对象的弱引用计数。
    其他数据,如自定义的删除器的指针(如果指定了自定义删除器)等。
控制块实际是由shared_ptr创建出来的,而后,当使用shared_ptr对象创建weak_ptr对象时,weak_ptr对象也指向了这个控制块。具体后面还会讲到shared_ptr的控制块,到时再细讲。

这篇关于16.3 C++智能指针-weak_ptr的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/migu123/article/details/128848431
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/234643

相关文章

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方