C++——C++11(2)

news2025/7/19 11:52:54
我在我的C++异常博客中曾提到,对于异常的处理经常会导致内存泄漏问题,
一种解决方法是异常的重新抛出,还有一种就是RAII,那么RAII的思想体现
在C++中就是智能指针,所以接下来我将简单的介绍,什么是RAII,以及什
么是智能指针。

1. 初识智能指针

在学C++的人,还没有接触智能指针的时候,就会想智能指针到底是什么啊?它真的是智能的吗?其实智能指针只是人们给它起了个这样的名字,它并不是智能的。
我们首先来解决异常博客中,如何使用RAII的思想很好的解决内存泄漏问题:
在这里插入图片描述
在这里插入图片描述
可以看到在程序执行中,只是开辟了空间,而没有释放。原因就是异常抛出后,如果有接收异常的地方,执行流会直接跳跃到匹配的catch中,而不执行中间栈帧的后续代码(但是会销毁中途的栈帧),而开辟空间是在堆上,自然也就无法释放了。接下来给出RAII思想解决内存泄漏问题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到我们确实能够很好的将申请的资源释放,并且不需要我们自己手动释放。利用的原理也是当栈帧结束的时候,会调用栈帧中的自定义类的对象的析构函数,而我们利用这一点,正好可以将资源释放。而这可以说是RAII,但这也只是智能指针的雏形(因为它不具有指针的操作):
在这里插入图片描述

2. 智能指针的发展历程

智能指针其实在C++98中就有提出,只不过是在C++11中才被广泛认可。所以要研究好智能指针,顺着历史的发展来探索智能指针也未尝不可。

a. auto_ptr

在这里插入图片描述

auto_ptr是在C++98中提出的一种智能指针,它自然也遵循RAII。但是他有缺陷:
在这里插入图片描述
原因如下:
在这里插入图片描述
当使用赋值重载或者拷贝构造的时候,它会将资源的管理权转让,将原来的管理智能指针中的原生指针置为空,也就是对象悬空这样会导致使用者经常会出现访问越界的问题。这也是为什么C++11中智能指针才被广泛认可。
接下来我们简单实现一下auto_ptr:
在这里插入图片描述

在这里插入图片描述

b. unique_ptr

unique_ptr是C++11中提出的智能指针,它没有auto_ptr的缺点,因为它就不能将资源管理权进行转让(也就是无法使用赋值重载和拷贝构造)。
在这里插入图片描述
在这里插入图片描述

我们也可以试着自己实现一个简单的:
要实现对应的特性,我们可以只声明并且设为私有。
在这里插入图片描述
在这里插入图片描述
还有一种就是delete掉赋值重载和拷贝构造:

在这里插入图片描述

在这里插入图片描述
当然它也可以正常使用:
在这里插入图片描述

它的缺点也显而易见,就是同一处资源只能一个对象管理,所以就又有了shared_ptr。

c. shared_ptr

在这里插入图片描述
它的特点就是可以有多个shared_ptr对象共同管理同一处资源:
在这里插入图片描述
我们也可以自己实现,那么在实现的时候要实现多个对象共同管理一份资源,那就得使用引用计数了,但是这个引用计数的存储位置也必须是堆上开辟出来的,假如是成员变量的话就无法实现同一块资源有多少个shared_ptr对象管理了。假如是静态变量的话,如果程序中有两处资源需要shared_ptr管理也无法实现。
要注意:

计数只有在拷贝构造和赋值重载时才++。
析构时要根据引用计数来判断否真的释放资源。

实现如下:
在这里插入图片描述
在这里插入图片描述
它也有缺点:
在这里插入图片描述
在这里插入图片描述
可以看到这样设置节点是不正确的导致节点无法连接,所以应该是这样:
在这里插入图片描述
这样就会正常(这里多次释放不报错的原因是因为delete对空指针做了特殊处理):
在这里插入图片描述
但是这样就会出问题:
在这里插入图片描述
库中的也会出现这种问题:
在这里插入图片描述
在这里插入图片描述

这其中的逻辑如下:
在这里插入图片描述

就会导一直循环要释放从而无法释放资源。这种现象叫做循环引用。为了解决这种现象就又出现了weak_ptr。

weak_ptr

weak_ptr可以说是专门为了shared_ptr打辅助的,而它也不遵循RAII了。它其中提供了shared_ptr的构造函数,所以我们再来简单实现一手:
在这里插入图片描述
它没有析构函数,没有对资源进行管控,也就不遵循RAII,其中的get是获取shared_ptr的原生指针。
在这里插入图片描述
在这里插入图片描述
循环引用问题能够解决的原理是:使用weak_ptr之后没有增加两节点资源的引用计数,从而在析构时,能够很自然的释放资源

3. 定制删除器

在上面讲述中我们只是,delete了一块资源,那要是一块连续的资源呢?我们就需要使用delete[]来释放资源,那如何分别,究竟释放的是一块单一资源,还是一块连续的资源呢?C++把这个问题交给了程序员,所以就有了定制删除器,我们以unique_ptr举个例子:
在这里插入图片描述
这其中我们使用了可调用对象,包装器,模板来实现删除器的功能。

在这里插入图片描述
可以看到,不仅堆中的空间算资源,打开的文件也是资源,所以资源说的是很广泛的。

4. 总结

现在我们再回想一遍什么是RAII、智能指针?他们之间有什么关系?:

RAII它是一种思想,它其实就是利用了对象的生命周期的特点从而对资源达到控制。
而C++中的智能指针,它是RAII的一种体现,利用处于该栈帧中自定义类的析构函数
在栈帧结束时自动调用的特性,从而实现对资源的管控

而我们作为C++程序员,是必须要把内存泄漏这件事情看的非常非常非常重要的一件事:

1. 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。
ps:这个理想状态。但是如果碰上异常时,就算注意释放了,还是可能会出问题。
需要下一条智能指针来管理才有保证。
2. 采用RAII思想或者智能指针来管理资源。
3. 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功
 能选项。
4 出问题了使用内存泄漏工具检测。ps:不过很多工具都不够靠谱,或者收费昂贵。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

工具推荐:有哪些好用的SEO工具?

在现如今竞争激烈的互联网时代,网站优化是每个企业都需要关注的重要方面。为了提高网站在搜索引擎中的排名和曝光度,SEO(搜索引擎优化)工具成为了必不可少的帮手。本文将为大家推荐3款好用的SEO工具,感兴趣就接着往下看…

c++ qt 模态框和阻拦器 优先级 问题 修复 已解决

在c项目中。有 加载动画 和 模态框提醒的功能, 导致发生一个问题,有提示框的时候,动画也停止,必须点击 按钮 所有代码才能有效。 解决办法 谨慎使用 deleteLater,因为和模态框拦截有冲突, 使用 隐藏 或者 删除指针。 deleteLater 使用逻辑是 …

docker数据卷数据卷容器

前言 今天调休在家,随便玩玩,简单做下学习记录 1. 数据卷特点 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会被拷贝到新初始化的数据卷中数据卷可以在容器之间共享和重用可以对数据卷里的内容直接…

二分查找法详解(6种变形)

前言 在之前的博客中,我给大家介绍了最基础的二分查找法(没学的话点我点我!) 今天我将带大家学习二分法的六种变形如何使用,小伙伴们,快来开始今天的学习吧! 文章目录 1,查找第一个…

【动画图解】一次理清九大排序算法!面试官问到再也不慌!

排序算法 交换排序 冒泡排序快速排序 插入排序 直接插入排序希尔排序 选择排序 简单选择排序堆排序 归并排序基数排序桶排序 一、冒泡排序 冒泡排序是一种简单的交换排序算法,以升序排序为例,其核心思想是: 从第一个元素开始&#xff0c…

基于ssm二手车交易平台的设计论文

摘 要 进入21世纪网络和计算机得到了飞速发展,并和生活进行了紧密的结合。目前,网络的运行速度以达到了千兆,覆盖范围更是深入到生活中的角角落落。这就促使二手交易网站的发展。二手交易网站可以实现远程购物,远程选择喜欢的商品…

MACBOOK 通过iterm2连接堡垒机跳转服务器

本公司是通过齐治堡垒机连接远程服务器的环境,因为连接过程中需要自动输入密码和选择主机,所以要使用expect工具,编写expect脚本remote.exp #!/usr/bin/expectif { $argc ! 7 } {send_user "usage: expect $argv0 \[JUMP_HOST\] \[JUM…

算法模板之栈图文详解

🌈个人主页:聆风吟 🔥系列专栏:算法模板、数据结构 🔖少年有梦不应止于心动,更要付诸行动。 文章目录 📋前言一. ⛳️模拟栈1.1 🔔用数组模拟实现栈1.1.1 👻栈的定义1.1.…

window安装n报错

window11安装 n 时报以下错误 Unsupported platform for n9.2.0: wanted {“os”:“!win32”} (current: {“os”:“win32”}) 虽然执行 npm -g install n --force 可以强制安装 n,但是安装完成后,执行命令还是会报以下错误 ‘“bash”’ 不是内部或外部…

使用【OpenI启智平台】进行模型训练

前言 启智平台OpenI是一个人工智能开源开放平台,提供免费GPU算力可以进行模型训练。模式是git进行项目管理,可以创建调试任务调试代码以及保存镜像,创建训练任务训练模型,也提供推理和评测,我没用过就不讲述了。后来我…

多层负载均衡实现

1、单节点负载均衡 1)站点层与浏览器层之间加入了一个反向代理层,利用高性能的nginx来做反向代理 2)nginx将http请求分发给后端多个web-server 优点: 1)DNS-server不需要动 2)负载均衡:通过ngi…

docker-compose部署NebulaGraph图数据库

一、linux安装docker-compose 1.下载Docker Compose的可执行文件。可以使用以下命令下载最新版本: sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-comp…

25年老品牌 美好蕴育润康守护孕期妈妈的健康之路

孕期是每一位女性人生中最为特殊的阶段。每一位妈妈都期待着健康、快乐的度过每一天。然而,随着孕周的增加,孕期的不适和困扰也随之而来。孕吐、腰酸背痛、便秘等孕期症状让许多妈妈倍感疲惫和焦虑。在这个关键时刻,美好蕴育润康作为25年的老…

重学设计模式-Iterator(迭代器模式)

Iterator迭代器模式 介绍: 迭代器模式是一种行为型设计模式,它允许你在不暴露集合底层表示(并不知道集合底层使用何种方式对数据尽心存储)的情况下遍历集合中的元素。 这种模式提供了一种方法,可以顺序访问一个聚合…

Revit 二次开发 获取构件的某一层材质

如获取墙的结构材质:混凝土-现场浇筑混凝土 //拿到墙材质 WallType wallType (walls[i] as Wall).WallType; CompoundStructure wallCS wallType.GetCompoundStructure(); CompoundStructureLayer wallLayer wallCS.GetLayers().Where(r > r.Function Materi…

华为科技:辉煌发展、问题应对与未来战略

导言 作为全球领先的科技公司之一,华为经历了辉煌的发展历程。本文将深入探讨华为科技的发展过程、遇到的问题及解决过程、未来的可用范围,以及在各国的应用和未来的研究趋势。同时,分析在哪些领域华为能够取胜,以及在哪些方面发力…

IntelliJ IDEA 2023.3 新功能介绍

IntelliJ IDEA 2023.3 在众多领域进行了全面的改进,引入了许多令人期待的功能和增强体验。以下是该版本的一些关键亮点: IntelliJ IDEA mac版下载 macappbox.com/a/intellij-idea-for-mac.html 1. AI Assistant 的全面推出 IntelliJ IDEA 2023.3 中&am…

FPGA——XILINX原语(1)

FPGA——XILINX原语(1) 1.时钟组件(1)BUFG(2)BUFH(3)BUFR(4)BUFIO(5)使用场景 2.IO端口组件(1)IDDR&#xff0…

2. 创建型模式 - 抽象工厂模式

亦称: Abstract Factory 意图 抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。 问题 假设你正在开发一款家具商店模拟器。 你的代码中包括一些类, 用于表示: 一系列相关产品&…

竞赛保研 基于CNN实现谣言检测 - python 深度学习 机器学习

文章目录 1 前言1.1 背景 2 数据集3 实现过程4 CNN网络实现5 模型训练部分6 模型评估7 预测结果8 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于CNN实现谣言检测 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐&am…