【C++】12.智能指针

在上一篇博客【C++】11.异常中我们知道有些时候会造成内存空间的未释放从而导致内存泄漏,因此本篇博客的内容就是如何减少内存泄漏——智能指针。

一、RAII

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

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

下面这段程序就是使用RAII思想构造的智能指针的底板:

template<class T>
class SmartPtr
{
public:SmartPtr(T* ptr=nullptr):_ptr(ptr){}~SmartPtr(){if(_ptr)delete _ptr;}
private:T* _ptr;
};

二、智能指针的原理

上述的SmartPtr还不能将其称为智能指针,因为它还不具有指针的行为。指针可以解引用,也可以通过->去访问所指空间中的内容,因此:SmartPtr模板类中还得需要将* 、->重载下,才可让其像指针一样去使用。

template<class T>
class SmartPtr
{
public:SmartPtr(T* ptr=nullptr):_ptr(ptr){}~SmartPtr(){if(_ptr)delete _ptr;}T* operator->(){return _ptr;}T& operator*(){return *_ptr;}
private:T* _ptr;
};

三、智能指针的发展

3.1 auto_ptr

C++98版本的库中就提供了auto_ptr的智能指针。下面演示的auto_ptr的使用及问题。
auto_ptr的实现原理:管理权转移的思想,下面简化模拟实现了一份auto_ptr来了解它的原理,并不建议使用

namespace caryon
{template<class T>class auto_ptr{public:auto_ptr(T* ptr = nullptr) :_ptr(ptr) {}auto_ptr(auto_ptr& ap):_ptr(ap._ptr){ap._ptr = nullptr;}auto_ptr& operator=(auto_ptr& ap){if(_ptr!=ap._ptr){if(_ptr=nullptr)delete _ptr;_ptr = ap._ptr;ap._ptr = nullptr;}return *this;}~auto_ptr(){if (_ptr)delete _ptr;}T* operator->(){return _ptr;}T& operator*(){return *_ptr;}private:T* _ptr;};
}

3.2 unique_ptr

C++11中开始提供更靠谱的unique_ptr
unique_ptr的实现原理:简单粗暴的防拷贝,下面简化模拟实现了一份unique_ptr来了解它的原理

namespace caryon
{template<class T>class unique_ptr{public:unique_ptr(T* ptr = nullptr) :_ptr(ptr) {}unique_ptr(unique_ptr& ap) = delete;unique_ptr& operator=(unique_ptr& ap) = delete;~unique_ptr(){if (_ptr)delete _ptr;}T* operator->(){return _ptr;}T& operator*(){return *_ptr;}private:T* _ptr;};
}

3.3 shared_ptr

C++11中开始提供更靠谱的并且支持拷贝的shared_ptr
shared_ptr的原理:是通过引用计数的方式来实现多个shared_ptr对象之间共享资源

  1. shared_ptr在其内部,给每个资源都维护着一份计数,用来记录该份资源被几个对象共享。
  2. 在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。
  3. 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
  4. 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。
namespace caryon
{template<class T>class shared_ptr{public:shared_ptr(T* ptr = nullptr) :_ptr(ptr),_pcount(new int(1)) {}shared_ptr(shared_ptr& sp):_ptr(sp._ptr),_pcount(sp._pcount){(*_pcount)++;}shared_ptr& operator=(shared_ptr& sp){if(_ptr!=sp._ptr){~shared_ptr();shared_ptr(sp);}return *this;}~shared_ptr(){--(*_pcount);if (*_pcount==0){delete _ptr;delete _pcount;}}T* operator->(){return _ptr;}T& operator*(){return *_ptr;}private:T* _ptr;int* _pcount;};
}

循环引用

struct ListNode
{size_t val;caryon::shared_ptr<ListNode> _prev;caryon::shared_ptr<ListNode> _next;~ListNode(){cout << "~ListNode()" << endl;}
};
int main()
{caryon::shared_ptr<ListNode> n1(new ListNode);caryon::shared_ptr<ListNode> n2(new ListNode);n1->_next = n2;n2->_prev = n1;return 0;
}

在这里插入图片描述
这样的情况就有了weak_ptr

3.4 weak_ptr

namespace caryon
{template<class T>class weak_ptr{public:weak_ptr(){}weak_ptr(const shared_ptr<T>& sp):_ptr(sp.get()){}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}private:T* _ptr = nullptr;};
}

四、C++11和boost的关系

  1. C++ 98 中产生了第一个智能指针auto_ptr
  2. C++ boost给出了更实用的scoped_ptr和shared_ptr和weak_ptr
  3. C++ TR1,引入了shared_ptr等。不过注意的是TR1并不是标准版。
  4. C++ 11,引入了unique_ptr和shared_ptr和weak_ptr。需要注意的是unique_ptr对应boost的scoped_ptr。并且这些智能指针的实现原理是参考boost中的实现的。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

垃圾分类笔记YOLOV5(一)-pip换源-口罩识别-训练自己的数据集

pip换源网址 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple不进行配置的是临时换源 1、从github上下载YOLOV5的代码 翻墙软件clash 数据集地址roboflow clash配置一键导入 哔哩哔哩视频地址 数据集的下载格式&#xff1a; 2、修改自己的数据…

Webots与ROS1、ROS2接口变迁-2024-

三大免费仿真器CoppeliaSim、Gazebo和Webots。 Gazebo接口总结&#xff1a; Gazebo与ROS1、ROS2接口变迁-2005-2024--CSDN博客 缺点&#xff1a;版本绑定策略 早期webots版本和ros版本绑定 后期&#xff0c;webots接口最新版本和ros特定版本最匹配。 例如&#xff1a; 最好按…

Scrapy 分布式爬虫框架 Scrapy-Redis

github官网代码示例&#xff1a;https://github.com/rmax/scrapy-redis/blob/master/example-project/example/spiders/myspider_redis.py 什么是 Scrapy-Redis Scrapy-Redis 是一个基于 Scrapy 的扩展&#xff0c;用于实现分布式爬虫。它利用 Redis 作为分布式队列来共享待爬…

R 语言学习教程,从入门到精通,R 绘图饼图(23)

1、R 绘图 条形图 条形图&#xff0c;也称为柱状图条形图&#xff0c;是一种以长方形的长度为变量的统计图表。 条形图可以是水平或垂直的&#xff0c;每个长方形可以有不同的颜色。 R 语言使用 barplot() 函数来创建条形图&#xff0c;格式如下&#xff1a; barplot(H,xlab,…

JavaScript初级——DOM和事件简介

一、什么是DOM&#xff1f; 二、模型 三、对象的 HTML DOM 树 四、节点 浏览器已经为我们提供了文档节点对象&#xff0c;这个对象是window属性&#xff0c;可以再网页中直接使用&#xff0c;文档节点代表的是整个网页。 五、事件简介 事件&#xff0c;就是用户和浏览器之间的交…

【每日一题】【素数筛板子题】又是一年毕业季 牛客小白月赛99 D题 C++

牛客小白月赛99 D题 又是一年毕业季 题目背景 牛客小白月赛99 题目描述 样例 #1 样例输入 #1 3 4 2 4 6 5 5 6 2 5 3 2333333 8 11 4 5 14 19 19 8 10样例输出 #1 3 7 2做题思路 首先观察到 即需要保证拍照的时刻 大于等于 2 那么就从2开始往上走&#xff0c;如果有人…

【精选】推荐7款AI论文一键生成论文、开题报告和文献综述网站

在当前的学术研究和写作中&#xff0c;AI技术的应用已经变得越来越普遍。特别是对于论文、开题报告和文献综述的生成&#xff0c;许多平台提供了便捷的一键生成服务。以下是七款推荐的AI论文一键生成工具&#xff0c;包括千笔-aipaperpass。 1. 千笔-aipaperpass 千笔-aipape…

文心快码(Baidu Comate)初体验

文心快码&#xff08;Baidu Comate&#xff09;初体验 1文心快码简介和安装&#xff1a;简要介绍文心快码&#xff08;Baidu Comate&#xff09;、安装方法、使用方法等&#xff1b; Baidu Comate 是由百度自主研发&#xff0c;基于文心大模型&#xff0c;结合百度丰富的编程现…

主机安全-网络攻击监测

目录 概述暴力破解&#xff08;SSH爆破为例&#xff09;原理规则攻击模拟告警 端口扫描原理规则攻击模拟告警 流量劫持原理规则攻击模拟告警 参考 概述 本文介绍主机网络层面上的攻击场景&#xff0c;每种攻击场景举一个例子。监测方面以字节跳动的开源HIDS elkeid举例。 针对…

当前A股平均市盈率

再写一篇【不务正业】的 2023-08-23A股平均市盈率 来自乐咕乐股网 当前A股市盈率是否为低点&#xff1f; 不言而喻 ‌当前A股市场的市盈率确实处于相对低位。‌ 根据东方财富Choice最新数据显示数据&#xff0c;截至2024年8月23日&#xff0c;全A市盈率为13.06倍&#xff0c;…

初识C语言指针(3)

目录 1. 数组名的理解 2. 使⽤指针访问数组 3. ⼀维数组传参的本质 4. 冒泡排序 5. 二级指针 6. 指针数组 7. 指针数组模拟⼆维数组 结语 1. 数组名的理解 对于数组名想必大家并不陌生&#xff0c;数组名就是该数组首元素的地址&#xff0c;设想有一个arr 数组。我们…

解决github访问慢的问题

GitHub是全球开发者广泛使用的代码托管平台&#xff0c;但有时由于网络问题&#xff0c;访问速度可能会受到影响&#xff0c;这对于依赖GitHub进行日常开发工作的程序员来说是一个不小的困扰。为了解决这一问题&#xff0c;我们可以通过修改本地hosts文件来尝试提升访问速度。 …

如何将 Parallels Desktop 许可证密钥移至新的 Mac?

根据 Parallels 最终用户许可协议&#xff08;EULA&#xff09;的规定&#xff0c;您最多可以在一台设备上下载、安装和使用 Parallels Desktop 的一个原始副本。但是面对更换新机的用户&#xff0c;可以通过迁移的方式把 Parallels Desktop 许可证密钥移至新的 Mac&#xff0c…

大数据-91 Spark 集群 RDD 编程-高阶 RDD广播变量 RDD累加器 Spark程序优化

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

井盖异动传感器:为城市安全加码

城市的地下管网错综复杂&#xff0c;井盖作为连接地面与地下的重要通道&#xff0c;其安全性至关重要。然而&#xff0c;由于各种原因导致的井盖丢失或损坏事件时有发生&#xff0c;给行人和车辆带来了极大的安全隐患。 一、智能科技&#xff0c;守护脚下安全 旭华智能井盖异…

SpringBoot2:创建项目及启动时相关报错整理

1、创建时报错 Initialization failed for https://start.aliyun.com/ Please check URL, network and proxy settings.Error message: Error parsing JSON response换官网地址初始化即可&#xff1a;https://start.spring.io/ 那么&#xff0c;大家肯定会疑问&#xff0c;官网…

【Java】Spring Boot使用 Email 传邮件 (上手图解)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;4.1 认识依赖4.2 发送邮件步骤4.2.1 先获取授权码4.2.1 邮件配置4.2.2 主体内容…

堆《数据结构》

堆《数据结构》 1. 堆排序1.1 建堆向上调整建堆向下调整建堆 1.2 利用堆删除思想来进行排序1.3Top-k问题 2.堆的时间复杂度 1. 堆排序 1.1 建堆 建大堆 建小堆 向上调整建堆 AdjustUp建堆 void AdjustUp(HPDataType* a, int child) {// 初始条件// 中间过程// 结束条件int p…

【数据分析:RFM客户价值度模型】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本阶段和大家一起分享和探索大数据技术RFM客户价值度模型&#xff0c;本篇文章主要讲述了&#xff1a;RFM客户价值度模型等等。欢迎大家一起探索讨论&#xff01;&#xff01;&#xff01…

机械学习—零基础学习日志(如何理解概率论7)

这里需要先理解伯努利试验。只有A与A逆&#xff0c;两种结果。 正态分布 再来一道习题~&#xff1a; 解析&#xff1a; 《概率论与数理统计期末不挂科|考研零基础入门4小时完整版&#xff08;王志超&#xff09;》学习笔记 王志超老师 &#xff08;UP主&#xff09;