智能指针的使用

2023-05-16

智能指针在C++11版本之后提供,包含在头文件<memory>中,shared_ptr、unique_ptr、weak_ptr。

1,shared_ptr的使用

shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。

  • 初始化。智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,一个是类,一个是指针。例如std::shared_ptr<int> p4 = new int(1);的写法是错误的
  • 拷贝和赋值。拷贝使得对象的引用计数增加1,赋值使得原对象引用计数减1,当计数为0时,自动释放内存。后来指向的对象引用计数加1,指向后来的对象。
  • get函数获取原始指针
  • 注意不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存
  • 注意避免循环引用,shared_ptr的一个最大的陷阱是循环引用,循环,循环引用会导致堆内存无法正确释放,导致内存泄漏。循环引用在weak_ptr中介绍。

示例:

#include <iostream>
#include <memory>
void main()
{

	int a = 10;
	std::shared_ptr<int> ptra = std::make_shared<int>(a);
	std::shared_ptr<int> ptra2(ptra); //copy
	size_t size_1 =  ptra.use_count() ; // = 2
	int s1 = *(ptra.get());// = 10

	int b = 20;
	//std::shared_ptr<int> ptrb = pb;  //error
	std::shared_ptr<int> ptrb = std::make_shared<int>(b);
	
	/*
	* 原本ptra2是指向变量a的第二个智能指针,但是这里把它重新assign为指向变量b的智能指针。
	*所以指向变量a的智能指针引用计数减1,指向变量b的智能指针引用计数+1.
	*/
	ptra2 = ptrb; 

	size_t size_2 = ptra.use_count();//由2变1
	size_t size_3 = ptrb.use_count();//由1变2
}

2,unique_ptr的使用

unique_ptr“唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。相比与原始指针unique_ptr用于其RAII的特性,使得在出现异常的情况下,动态资源能得到释放。unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。

	int* ori = 0;
	{
		std::unique_ptr<int> uptr(new int(10));  //绑定动态对象
		ori = uptr.get(); 
		int x = *ori;// = 10
		int abc = 0;
		//std::unique_ptr<int> uptr2 = uptr;  //不能赋值
		//std::unique_ptr<int> uptr2(uptr);  //不能拷貝
		std::unique_ptr<int> uptr2 = std::move(uptr); //转移所有权
		int* tmp = uptr.get();// 由于uptr已经失去指向对象的所有权,所以这里得到的是一个空指针
		//int ddd = *tmp;  //err,访问空指针将报错
		

		uptr2.release(); //释放所有权,但是并不释放资源本身
		x = *ori;// = 10,这时没有任何std::unique_ptr指向ori地址的资源,但是资源还是存在的,访问他的值依然是10.
		tmp = uptr.get();// 由于uptr已经失去指向对象的所有权,所以这里得到的是一个空指针
		//int ddd = *tmp;  //err,访问空指针将报错

		abc = 0;
	}

离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作),测试如下:

	int* ori = 0;
	{
		std::unique_ptr<int> uptr(new int(10));  //绑定动态对象
		ori = uptr.get(); 
	}//由于离开了作用域,所以uptr释放了他所指向的资源
	int y = *ori;//此时ori只是一个野指针,y为一个随机值。

3,weak_ptr的使用

weak_ptr是为了配合shared_ptr而引入的一种智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。weak_ptr可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count()==0,但更快,表示被观测的资源(也就是shared_ptr的管理的资源)已经不复存在。weak_ptr可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象, 从而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr。


	{
		std::shared_ptr<int> sh_ptr = std::make_shared<int>(10);
		std::cout << sh_ptr.use_count() << std::endl; // 输出1

		std::weak_ptr<int> wp(sh_ptr);
		std::cout << wp.use_count() << std::endl;    // 输出1
		std::cout << sh_ptr.use_count() << std::endl; // 输出1

		if (!wp.expired())
		{
			std::shared_ptr<int> sh_ptr2 = wp.lock(); //get another shared_ptr
			*sh_ptr2 = 100;
			std::cout << *sh_ptr.get() << std::endl;  // 输出100
			std::cout << wp.use_count() << std::endl; // 输出2
		}
	}
	//delete memory

本文参考:C++11中智能指针的原理、使用、实现 - wxquare - 博客园

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

智能指针的使用 的相关文章

  • 什么是手机的IMEI?

    一 xff0c IMEI是什么 xff1f IMEI xff08 International Mobile Equipment Identity xff09 是移动设备国际身份码的缩写 是由15位数字组成的 电子串号 xff0c 该码是全球
  • PBOC2.0安全系列之—脱机认证之静态数据认证(SDA)

    PBOC2 0安全系列之 脱机认证之静态数据认证 SDA 一 xff0c 什么是PBOC2 0 2005年3月13日 xff0c 人民银行发布第55号文 xff0c 正式颁发了 中国金融集成电路 xff08 IC xff09 卡规范 简称P
  • 第三方支付架构设计之—帐户体系

    第三方支付架构设计之 帐户体系 一 xff0c 什么是第三方支付 xff1f 什么是第三方支付 xff1f 相信很多人对这个名字很熟悉 xff0c 不管是从各种媒体等都经常听到 xff0c 可以说是耳熟能熟 但 xff0c 如果非得给这个名
  • ELF文件格式详解

    ARM的可执行文件的格式是ELF格式文件 xff0c 下文对ELF格式做个详细的介绍 序言 1 OBJECT文件 导言 ELF头 ELF Header Sections String表 String Table Symbol表 Symbol
  • ROS小车(SLAM+物体追踪)

    属于交通运输工程设计的论文 xff0c 包含SLAM与物体追踪这两个方向 ROS智能车设计 一 系统描述 1 车轮子 单轮平衡式结构 xff0c 能量利用率高 xff0c 但转弯的时候需要倾角高速运动 xff0c 很难控制 差速转向平衡两轮
  • 配置apache服务器的用户认证

    经常上网的读者会遇到这种情况 xff1a 访问一些网站的某些资源时 xff0c 浏览器弹出一个对话框 xff0c 要求输入用户名和密码来获取对资源的访问 这就是用户认证的一种技术 用户认证是保护网络系统资源的第一道防线 xff0c 它控制着
  • 强大的grep用法详解:grep与正则表达式

    from http hi baidu com nearlove blog item 11db98b6b5b8aff831add1e5 html 首先要记住的是 正则表达式与通配符不一样 它们表示的含义并不相同 正则表达式只是一种表示法 只要
  • Linux中通过/proc/stat等文件计算Cpu使用率

    from xff1a http www blogjava net fjzag articles 317773 html proc文件系统 proc文件系统是一个伪文件系统 xff0c 它只存在内存当中 xff0c 而不占用外存空间 它以文件
  • 关于mysql的错误 - no query specified

    Mysql error no query specified mysql下抛出错误 xff1a error no query specified 出现此错误是sql不合法原因 xff1a 如 xff1a select from abc G
  • 详解coredump

    一 xff0c 什么是coredump 我们经常听到大家说到程序core掉了 xff0c 需要定位解决 xff0c 这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止 xff0c 并且在满足一定条件下 xff0
  • freertos 源码详解四 堆栈初始化

    在prvInitialiseNewTask函数中 xff0c 有一个步骤7 xff1a pxNewTCB gt pxTopOfStack 61 pxPortInitialiseStack pxTopOfStack pxTaskCode pv
  • STL - vector

    C 43 43 STL中的verctor好比是C语言中的数组 xff0c 但是vector又具有数组没有的一些高级功能 与数组相比 xff0c vector就是一个可以不用再初始化就必须制定大小的边长数组 xff0c 当然了 xff0c 它
  • 计算机专业术语,收藏用

    显示内存 与主板上的内存功能一样 xff0c 显存也是用于存放数据的 xff0c 只不过它存放的是显示芯片处理后的数据 显存越大 xff0c 显示卡支持的最大分辨率越大 xff0c 3D应用时的贴图精度就越高 xff0c 带3D加速功能的显
  • 7_资源文件添加

    资源文件添加 在QMainWindow中我们已经设立了一些部件 xff0c 现在我们来设置图标 通常有相对路径读取和资源文件读取两种方法 QAction actionNew 61 new QAction 基本格式 ui gt actionN
  • 智能除草机

    专利设计 xff1a 智能除草机 1 除草机背景 业界主要采用滚刀式草坪修剪车来进行运动场的除草 除草不仅浪费人力 xff0c 而且也受到天气状况的限制 传统割草机产生的环境污染也较大 随着社会经济的不断发展 xff0c 人力成本也不断攀升
  • nodejs解析http协议源码解析

    上篇文章讲到nodejs创建一个服务并且建立tcp连接的过程 接下来分析一下 xff0c 在建立tcp连接后 xff0c nodejs是如何解析http协议的 我们首先看一下nodejs在建立tcp连接时执行net js层的回调时做了什么操
  • template模板及模板类的实例化

    模板template 通常 xff0c 当我们调用一个函数时 xff0c 编译器只需要掌握函数的声明 类似的 xff0c 当我们使用一个类类型的对象时 xff0c 类定义必须是可用的 xff0c 但成员函数的定义不必已经出现 因此我们将类定
  • java学习简记录(四)

    java学习简记录 xff08 四 xff09 Java 程序是一系列对象的集合 xff0c 这些对象通过调用彼此的方法来协同工作 对象 xff1a 对象是类的一个实例 xff0c 有状态和行为 类 xff1a 类是一个模板 xff0c 它

随机推荐

  • VS2015+QT5.6.1环境配置后,在VS中双击无法打开*.ui文件

    在环境都搭建好以后 xff0c 在VS中新建了一个QT界面工程 双击 ui后 xff0c 期望得到Qt designer那种直接进入拖拉控件进行编辑的操作界面 but 并不能得到预期结果 解决方法如下 第1步 xff1a 在 解决方案资源管
  • 求字符串的最长回文

    主要锻炼的就是动态规划的思想 xff01 xff01 xff01 掌握这种思想 xff0c 工作中不一定用得上 xff0c 但是多一种思想就多一种可能 span class token comment dp i j 表示s的子串 xff08
  • C++查找指定目录下的特定后缀文件并按照创建时间排序

    在一个项目中 xff0c 遇到了这个需求 于是windows 43 vs平台上实现了这个功能Demo 测试完毕后移植到了具体的项目中 span class token macro property span class token dire
  • Ubuntu下Qt程序生成Core文件便于调试

    需要在运行时生成core dump文件 xff0c 以排查出错的代码行 首先在pro结尾里加入 xff1a QMAKE CC 43 61 g QMAKE CXX 43 61 g QMAKE LINK 43 61 g 在终端输入 ulimit
  • linux查看进程所有子进程和线程

    线程是现代操作系统上进行并行执行的一个流行的编程方面的抽象概念 当一个程序内有多个线程被叉分出用以执行多个流时 xff0c 这些线程就会在它们之间共享特定的资源 xff08 如 xff0c 内存地址空间 打开的文件 xff09 xff0c
  • 一款二进制文件查看器

    由于使用的是Notepad 43 43 64位版本 xff0c 在网上找了很多二进制查看插件HexEditor dll要么是32位不兼容 xff0c 要么是出现除零的错误 xff08 以前找到过一次支持Notepad 43 43 64位版本
  • YOLO目标检测

    一 背景 基于深度学习技术的视觉目标检测近年去的长足发展 但仍然有许多方面问题需要优化 二 YOLO算法的特点 YOLO作为一种性能优异的通用目标检测系统 xff0c 为了保证检测的效率 xff0c 提出one stage的思想 xff0c
  • (Qt中添加编译选项)QT在交叉编译时出现parameter passing for argument of type ‘std::_Rb_tree xxxxx changed in GCC 7.1

    QT版本都是5 1x 先是在Ubuntu机器上写的代码 xff0c GCC版本为5 4 xff0c 代码编译无 任何警告 后来移植到开发板 xff08 GCC版本为7 1 xff09 进行编译时 xff0c 提示这种警告 发生在代码中对st
  • C++按行读取文本并解析

    项目中需要按行读取文本文件 xff0c 并对每一行内容进行解析 每一行都是固定的字段数 xff0c 字段之间用空格隔开 span class token macro property span class token directive k
  • error C2447: “{”: 缺少函数标题(是否是老式的形式表?)

    error C2447 缺少函数标题 是否是老式的形式表 网上有人说 这个BUG是因为在win7上使用了 LF 的格式编码导致的 使用Notepad 43 43 修改成 BOM UTF8 和 windows 的 CR LF 格式一切正常 确
  • Visual Studio 2017 代码自动对齐

    点 编辑 高级 设置选定内容的格式 或者按Ctrl 43 K 然后再按Ctrl 43 F 就好了 你可以在常用快捷键自定义 窗口中进行查看 1 进入工具 选项 对话框 2 选择 环境 键盘 3 在 显示命令包含 下面的对话框中输入 对齐 关
  • CSDN 排版之颜色、字体、字号及背景色

    颜色 xff1a span class token operator lt span font color span class token operator 61 span blue span class token operator g
  • 使用QTCreator编程时,如何利用dmp文件定位程序奔溃

    写这篇文章之前 xff0c 看了一些其他人的博客 xff0c 但不是很详细 xff0c 缺这少那的 xff0c 好多都是复制粘贴别人的东西 自己动手弄了弄 xff0c 可以使用 xff0c 就记下来备忘与分享 前言 开发环境说明 编程IDE
  • Pytorch中transforms.RandomResizedCrop使用说明

    加载数据 训练集数据扩充 数据增强 和归一化 数据扩充 数据增强 的意义在于通过人为的随机范围裁剪 缩放 旋转等操作 增大训练集中的数据多样性 全面性 进而提高模型的泛化能力 训练集数据扩充和归一化 在验证集上仅需要归一化 data tra
  • C++中调用Python的办法

    1 背景 一直采用C 43 43 作为主语言开发 xff0c 最近遇到一个项目需要解析PDF文件中的文本内容 xff0c 直接采用C 43 43 来做显得不是很方便 xff0c 但用python来做就显得很简单了 难点在于如何C 43 43
  • Qt Creator远程调试嵌入式ARM开发板

    1 环境 Win10 64位系统上通过Virtual Box安装了一个Ubuntu虚拟机 ubuntu的版本 xff1a Linux kernel 4 15 0 142 generic 146 16 04 1 Ubuntu SMP Ubun
  • 套接字(描述符)读取指定的字节数

    检测fd句柄是否可读 xff0c ms毫秒超时 参数 xff1a df in 检测的句柄 ms in 超时 xff0c 毫秒 返回 xff1a 1 可读 xff0c 或者已经断开 0 超时 xff0c 仍然不可读 1 错误 int IsRe
  • 4.4线索二叉树遍历

    1 中序线索二叉树遍历 找到第一个中序遍历的结点 ThreadNode span class token operator span span class token function Firstnode span span class t
  • 自动根据本机字节序 将小端字节序的报文(字符数组)转为整数

    1 xff0c 判断本机的字节序 xff08 大端优先 小端优先 xff09 判断当前PC为大端还是小端字节序 64 返回值 xff1a 1 大端 xff1b 0 小端 int JudgeEndianOfPC int num 61 1 if
  • 智能指针的使用

    智能指针在C 43 43 11版本之后提供 xff0c 包含在头文件 lt memory gt 中 xff0c shared ptr unique ptr weak ptr 1 xff0c shared ptr的使用 shared ptr使