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

陈硕智能指针线程安全_「C++基础篇」智能指针 auto_ptr/unique_ptr/shared_ptr

43bf04f925972f8d63375ab5b54f7e27.png

指针与动态内存管理(堆)

541e66a7de655436ebfbd32c93c7c857.png

从上述代码中,可以很明显的发现其中的问题。每当调用函数时都会从堆中分配内存,但却在操作结束后没有进行内存回收。这将导致内存泄漏。一般而言,不能很好的对内存进行管理的C++程序员不是一个合格的程序员。

一种解决方法就是,时时刻刻都记得释放自己申请的内存。这不是一件简单的事,特别是在大型项目开发过程中。

09ab838f3a5dee26b900f2b4820197a2.png

当dosomething发生异常时,line 4将不会被执行

时刻记得释放内存并不能总能有效。当发生异常的时候,delete ps将不会被执行,进而导致内存泄漏。

那如何能保证任何时候都能做到对申请的堆内存进行释放了?

我们知道的是当函数dosomething()结束时(无论是正常返回还是异常终止),局部变量都会结束生存周期,也就是指针变量ps将会被释放。如果ps释放时,其指向的内存也能被释放这不就满足我们的目的--总是做到对申请的内存进行释放了吗?深刻理解面向对象编程理念的话,这种情况可以使用析构函数做到,也就是对象消亡时调用对象的析构函数对其指向的动态内存进行释放--这就是智能指针的核心思想!

为什么需要智能指针

① 通过智能指针的析构函数,自动管理内存释放。

② 智能指针可以确保总能正常释放内存,即使是异常发生。

如何设计智能指针

971500b9932ac78f23cd99523195df52.png

指针p1和p2指向了同一块内存

为了不出现多指针指向统一内存区(其实不必过度考虑这一点,如后面将讲到的shared_ptr是允许多个指针指向同一内存的),初始的智能指针模板类进行了如下设计:

a) 定义赋值运算符,执行深拷贝。使指针指向不同对象。

b) 建立所有权,对于特定的对象只能有一个智能指针拥有它,使用移动赋值函数转让权限,使只有拥有对象的智能指针可以删除对象。如,auto_ptr。

7d98f6421a58c7cf51ad2883a30b7276.png

对ap2进行赋值操作即使转移ap的所有权,但会留下悬浮ap

但这种auto_ptr运行直接转让权限的操作将会导致留下悬浮指针ap,它将不会再指向有效数据,如果程序后面试图使用ap这将导致出现不确定行为或者崩溃。因此unique_ptr被设计出。

unique_ptr比auto_ptr更安全

72521db847f8c8eb0822d1b3ebe40059.png

line 9是不被运行的,而line 12对临时对象转移权限是被允许的

unique_ptr不允许对一个左值进行权限转移,因为这会留下一个有隐患的悬浮指针(不理解悬浮指针的危害的请查看本人的之前【「C++基础篇」深拷贝与浅拷贝】文章)。但允许对右值临时对象进行权限转移操作,因为右值临时对象将在转移完权限后就销毁。

unique_ptr允许申请数组内存unique_ptr up(new double[5]),auto_ptr不能。

shared_ptr最为贴近原始的指针

就像前面说的,多个指针指向同一个内存并非不可以,只要正确的释放内存即可。而shared_ptr使用引用计数做到了这一点使得智能指针更加贴近原始的指针

991bd7e24ecfb668eba6cc47c11949ad.png

赋值时计数加1,指针过期时计数减1。当最后一个指针过期时,才调用delete。这是shared_ptr。

shared_ptr可以接收一个临时的unique_ptr右值但不能指向unique_ptr左值。

除了上面的几个智能指针外,还有weak_ptr,这将会在以后的多线程篇中仔细讲解。

相关文章:

  • easyui是否容易上手_bootstrap 和 jQueryEasyUI 哪个做后台管理系统更好一些?
  • column分栏布局只是文字布局吗_写给自己看的CSS columns分栏布局教程
  • 定时备份mysql脚本_自动定时备份 mysql 数据库 的 shell 脚本
  • mysql存储xml_mysql存储xml数据 mysql和sql server
  • 使用php mysql js实现聊天功能_php实现简单聊天功能
  • 帝国cms与mysql数据库_如何使用帝国CMS自带的数据库类
  • mysql所有选修课程都及格_MySQL 练习题目 二刷 - 2019-11-4 5:55 am
  • c3p0连接池配置 mysql_C3P0连接池配置详解 + 数据库主从配置
  • mysql查看字符出现次数_mysql 查找一个列中,一个字符出现的次数
  • windows 发包工具_ksubdomain 无状态域名爆破工具
  • epel mysql_RHEL/CentOS 6.x使用EPEL6与remi的yum源安装MySQL 5.5.x
  • j2ee mysql struts_j2ee 整合 struts2.3.4
  • mysql加快备份_mysqldump 备份直接至压缩文件,提高备份及压缩时间
  • mysql的to char data_MySQL_MySQL中数据类型的验证,CHAR char (M) M字符,长度是M* - phpStudy...
  • pusg跳转传参 vue_Vue 路由跳转、传参、接参四种方式
  • Android 控件背景颜色处理
  • crontab执行失败的多种原因
  • CSS实用技巧
  • JAVA SE 6 GC调优笔记
  • JavaScript类型识别
  • Ruby 2.x 源代码分析:扩展 概述
  • 包装类对象
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 构建二叉树进行数值数组的去重及优化
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 简单基于spring的redis配置(单机和集群模式)
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 三分钟教你同步 Visual Studio Code 设置
  • 微信小程序填坑清单
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • # C++之functional库用法整理
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • (06)金属布线——为半导体注入生命的连接
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (16)Reactor的测试——响应式Spring的道法术器
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (3)llvm ir转换过程
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (五)网络优化与超参数选择--九五小庞
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • .NET 8.0 发布到 IIS
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .net web项目 调用webService
  • .NET命令行(CLI)常用命令
  • @AutoConfigurationPackage的使用
  • [ 网络基础篇 ] MAP 迈普交换机常用命令详解
  • [Android Pro] Notification的使用
  • [BROADCASTING]tensor的扩散机制