智能指针管理“newed对象”

为什么要有智能指针?

指针智能是管理管理动态内存分配对象的一种机制。它提供了自动管理内存,避免常见内存泄漏和悬空指针。

对于上述Func函数的操作,一不小心就会产生很多问题。

  • p1 new时候抛异常 什么都不做
  • p2 new时候抛异常 p1需要被清理
  • div除0错误 p1 p2 都需要清理

上述代码我们也实现了delete,但是却有没被调用的风险。

资源没有被回收,就会导致内存泄漏,内存越用越多,如操作系统会卡死。

自动管理资源——智能指针

RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源
        在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:

  • 不需要显式地释放资源。
  • 采用这种方式,对象所需的资源在其生命期内始终保持有效

指针智能就是针对RAII思想设计的一种管理资源的方法;


智能指针的使用

1)利用对象生命周期管理

智能指针的基本使用思路。将对象通过指针交给一个类,类在调用的时候,构造完成初始化,析构完成自动清理资源。


解决上述问题

创建对象sp1 sp2时,会调用构造函数,将new int 构造类中的指针。在sp1 sp2的生命周期结束时(栈帧的销毁)会调用对象的析构函数 ,将动态开辟的内存释放掉

new sp1异常 什么都不做 没有任何构造

new sp2 异常栈帧会跳转到catch 局部变量sp1会被销毁,调用析构

div()函数出异常 局部变量sp1和sp2的栈帧都要被销毁,自动调用析构函数

上述操作就是将一个对象托管给另一个对象管理资源。就是RAII的思想 


*和->

为了让智能指针能够像指针一样操作。我们将智能指针进行操作符重载。*(解引用)和&(取地址)。


浅拷贝问题

利用上述的指针管理资源。不适合拷贝对象。

类中对于拷贝操作默认是浅拷贝,就是将对象资源按照字节一个个拷贝过去。

对于本题中,new开辟一块空间,将空间的地址交给智能指针构造出sp1,由sp1管理资源。

而在第二步拷贝赋值中,将sp1的地址一个字节一个字节拷贝给sp2,因此二者指向同一块空间。

在对象生命周期结束时,会自动调用析构函数。sp1和sp2指向同一块空间。一块空间delete俩次,所以会产生错误。

怎么解决?

这里就从历史的角度谈谈


auto_ptr

在C++98中,提出管理权限转移的思想。

假定都是sp1做为要被覆盖的对象

  • 在拷贝构造和赋值时,将被赋值对象的资源转移到自身。
  • 在拷贝构造时-----sp2指针的地址转为空
  • 在赋值时------需要检查是否自己赋值自己!然后需要释放sp1的内存,将sp2的内存转移到sp1上

将sp2的指针悬空

由于资源管理权限被转移,指针存在悬空。

unique_ptr

在C++98和C++11之间产生了非官方库 boost

unique_ptr

简单粗暴----防止拷贝

在成员函数中,如果不写拷贝构造函数和赋值运算符,编译器就会自动生成默认函数。如果我们显示的实现,而不再赋值上操作。如果只是声明,不写实现,那么有可能在类外被实现。

因此要在类内实现声明,并且声明为私有

在C++11中,delete关键字禁止生成默认函数


三 

shared_ptr

shared_ptr 其实就是对资源做引用计数——当引用计数为 0 的时候,自动释放资源。

比如我们有俩个对象同时指向同一块空间(sp1,sp2)。如果sp1被销毁了,就会什么也不做。然后空间配套的引用计数就会从2减到1。如果当sp2也要被释放时,引用计数从1减到0,此时计数为0,就要释放这块空间。

简单的来说shared_ptr包含俩部分

  • 一个指向堆上创建的裸指针
  • 一个指向内部隐藏的、共享的管理对象 count代表被多少对象引用共享了,也就是引用对象。

计数器设为全局吗?

在C++中用全局变量要非常谨慎。

如果将计数器设为全局,那么计数器就属于全部的类,该类的任何一个对象的增加或减少,都会影响计数器。因此需要对每一块资源分配一个计数器。

  • 构造:为_pcount开空间
  • release():减计数不为0不操作,计数为0时,删除空间
  • 赋值:检查自己赋值自己,释放旧空间 更新_pcount 
  • 拷贝构造:拷贝地址和_pcount ,更新_pcount
  • 基本指针操作

循环引用的解决

shared_ptr指针还存在循环引用的问题,再下一篇文章中将作为重点探讨,同时介绍weak_ptr。

总结


1. 尽量使用智能指针管理资源申请与释放,减少人为new和delete误操作和考虑不周的问题。

2.RAII思想就是利用变量生命周期管理资源。

点我gitee提取代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/245084.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Apache DolphinScheduler 社区荣获 “2023 年度优秀开源技术团队“ 奖项

在开源社区日益繁荣的今天,我们非常荣幸地宣布:Apache DolphinScheduler 社区在 OSCHINA 平台的评选中荣获了“2023 年度优秀开源技术团队”奖项。这一奖项反映了我们社区在过去一年里在内容发表的深度与广度、活动运营影响力以及对开源文化的推广方面所…

每日一题 --- 2477. 到达首都的最少油耗

链式前向星解法 核心点是我dfs两次,第一次是求出每个节点的叶子节点有多少个? 因为我们可以看做从当前节点出发到当前节点的根节点的话,那么需要知道当前节点叶子节点个数,也就是我们让当前节点的叶子结点(代表&…

yolov8常用命令

1.运行预测 (1)运行目标检测模型: yolo predict modelyolov8n.pt sourcebus.jpg (2)运行目标检测与分割模型 yolo predict modelyolov8n-seg.pt sourcebus.jpg 2.模型训练 复制coco128.yaml更名为myDetect.y…

检测车牌的SIFT特征并匹配

# 代码5-14 检测车牌的SIFT特征并匹配 import cv2img1 cv2.imread(../data/plate.jpg) img2 cv2.imread(../data/car.jpg)sift cv2.SIFT_create() # 利用sift.detectAndCompute()函数找到特征点,计算描述符; kp1, des1 sift.detectAndCompute(img1, …

Unity Sentis首份教程来啦,利用AI模型创建先进功能

Unity 推出的 Sentis,赋予开发者将 AI 模型导入游戏和应用程序中的能力。现在,Sentis 已进入预发布的开放测试阶段,用户可以在所有类型的项目中实现物体识别、语音识别和智能 NPC 等复杂功能。 这些 AI 模型一旦通过 ONNX 文件标准导入&…

地图自定义省市区合并展示数据整合

需求一:将省级地图下的两个市合并成一个区域,中间的分割线隐藏。 1、访问下方地址,搜索并下载省级地图json文件。 地址:https://datav.aliyun.com/portal/school/atlas/area_selector 2、切换到边界生成器,上传刚刚下…

基于Java+SpringBoot+Vue3+Uniapp前后端分离考试学习一体机设计与实现企业级2.01版本(视频讲解,已发布上线)

博主介绍:✌全网粉丝5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…

【经验分享】gemini-pro和gemini-pro-vision使用体验

Gemini Gemini已经对开发者开放了Gemini Pro的使用权限,目前对大家都是免费的,每分钟限制60条,至少这比起CloseAI的每个账户5刀限速1min3条要香的多,目前已于第一时间进行了体验 一句话总结,google很大方,但…

web服务器之——搭建两个基于域名访问的网站

目录 要求: 一、准备工作:web服务器搭建 第一步:挂载 第二步:编辑配置文件 第三步:安装软件包 第四步:启动httpd 查看配置文件: 第五步:设置防火墙状态: 重启服务…

虹科技术 | IO-Link Wireless如何赋能工厂车间迈向无线自动化?

大规模定制、卓越运营和商业智能正在从根本上改变制造业,为了在竞争中立于不败之地,制造商需要更加灵活、通用、可扩展和具有成本效益的机器和生产线。随着制造商向工业 4.0 迈进,更好的适应性、更高的吞吐量和更短的停机时间是他们的共同要求…

【C++】策略模式

目录 一、简介1. 含义2. 特点 二、实现1. 策略接口(Strategy Interface)2. 具体策略类(Concrete Strategies)3. 上下文类(Context)4. 使用策略模式 三、总结如果这篇文章对你有所帮助,渴望获得你…

【Java系列】详解多线程(二)——Thread类及常见方法(下篇)

个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习Java的一点学习心得,欢迎大家在评论区交流讨论💌 目录 一…

删除员工信息和全局异常处理

删除员工: 删除员工信息,根据员工的id删除其实批量删除就是一种特殊的批量删除,所以,删除员工的功能,我们只需要开发一个接口就可以了。 删除员工的逻辑分析: controller层获取请求的参数: 接收…

大模型微调的“温度”参数,原来影响的是 softmax

大家好啊,我是董董灿。 在对大模型进行微调训练时,经常会看到几个重要的超参数,用来控制大模型生成文本的效果。 其中一个超参数叫做 Temperature,中文名字叫温度,初见时很是不解,为啥一个模型还有温度这个…

【问题处理】—— lombok 的 @Data 大小写区分不敏感

问题描述 今天在项目本地编译的时候,发现有个很奇怪的问题,一直提示某位置找不到符号, 但是实际在Idea中显示确实正常的,一开始以为又是IDEA的故障,所以重启了IDEA,并执行了mvn clean然后重新编译。但是问…

36、什么是池化算法

池化算法也是 CNN 网络中非常常见的算法。 池化这一算法理解起来比较简单,从名字中或许可以看到一些东西:从一个像素池子中选取一些有代表性的像素出来。 常见的池化有最大池化和平均池化。最大池化就是从像素池子中选取最大值出来,而平均池化就是从像素池子中选取平均值出…

Ganache结合内网穿透实现远程或不同局域网进行连接访问

文章目录 前言1. 安装Ganache2. 安装cpolar3. 创建公网地址4. 公网访问连接5. 固定公网地址 前言 Ganache 是DApp的测试网络,提供图形化界面,log日志等;智能合约部署时需要连接测试网络。 Ganache 是一个运行在本地测试的网络,通过结合cpol…

一文搞清楚“并发与并行”“串行与并行”“线程与进程”的区别

目录 🐶6.1 并发与并行 🐶6.2 串行与并行 1. 基本概念 2. 举个🌰 3. 适用场景 🐶6.3 线程与进程 1. 基本概念 2. 进程与线程的区别 3. 线程调度: 🐶6.1 并发与并行 并行:指两个或多个事件在同一时…

2023年OceanBase开发者大会-核心PPT资料下载

一、峰会简介 2023年OceanBase开发者大会主要涵盖了OceanBase的最新技术进展、产品更新以及开发者工具的发布。大会发布了OceanBase 4.1版本,公布了两大友好工具,升级了文档的易用性,并统一了企业版和社区版的代码分支。这些举措全面呈现了O…

【算法题】开源项目热度榜单(js)

解法 const lines ["4","8 6 2 8 6","camila 66 70 46 158 80","victoria 94 76 86 189 211","athony 29 17 83 21 48","emily 53 97 1 19 218", ]; const lines2 ["5","5 6 6 1 2","…