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

【C++】智能指针思路解析和模拟实现

此篇文章就从以下几个方面出发,带你了解智能指针的方方面面


1.为什么需要智能指针


当我们开辟内存并使用的时候,我们的顺序应该是这样:

开辟内存-》使用内存-》释放内存

问题就出现在第三步,开辟好了,也使用了,但是释放的时候出现了问题,可能是malloc没有释放,也可能是抛异常之后跳过了回收,不管怎样,此时就会发生内存泄漏。


2.内存泄漏之后


内存使用空间的减小,运行卡顿,死机等。

内存泄漏可以分为:

堆内存泄漏(Heap leak) 堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存, 用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那 么以后这部分空间将无法再被使用,就会产生Heap Leak。

系统资源泄漏 指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统 资源的浪费,严重可导致系统效能减少,系统执行不稳定。

解决办法(知道即可)

通过内存泄漏的一些检查工具,这里可以参考其他博客,此篇不做详解。


3.如何避免内存泄漏


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

简单可以分为内存泄漏之前的预防,事后的检查,这里要讲的就是事前的预防。


4.智能指针


我们知道,在类创建的时候会调用构造函数,在析构的时候会调用析构函数,所谓的智能指针,其实就是将创建的对象并不直接创建,而是交给一个模板类,通过这个模板类来帮助我们管理。

这里说三种智能指针的设计,

auto_ptr
// C++库中的智能指针都定义在memory这个头文件中
#include <memory>
class Date
{
public:Date() { cout << "Date()" << endl;}~Date(){ cout << "~Date()" << endl;}int _year;int _monthint _day;
};
int main()
{auto_ptr<Date> ap(new Date);auto_ptr<Date> copy(ap);ap->_year = 2018;return 0;
}

这是它的使用,下面看一下源代码:

template<class T> 
class auto_ptr 
{ T* p; 
public: auto_ptr(T* s) :p(s) {} ~auto_ptr() { delete p; } auto_ptr(auto_ptr& a) { p = a.p; a.p = NULL; } auto_ptr& operator=(auto_ptr& a) { delete p; p=a.p; a.p = NULL; return *this; } T& operator*() const { return *p; } T* operator->() const { return p; } 
}; 

可以看到,当它作为智能指针赋值的时候,会出现讲前面置空的情况,如果我们之后还需要使用前面一个,就会发生报错。

不过这里简单的模拟实现一个:

    template<class K>class auto_ptr{public:auto_ptr(K* ptr):_ptr(ptr){}
​~auto_ptr{if (_ptr){cout << "delate" << endl;delete _ptr;_ptr = nullptr;}}
​//auto k(auto k1)auto_ptr(auto_ptr<K>& k1):_ptr(k1._ptr){k1._ptr = nullptr;}
​//一些指针的操作K& operator&(){return *_ptr;}
​K* operator*(){return _ptr;}
​
​private:K* _ptr;};

不推荐,平时也不会用,看看就好。

shared_ptr

顾名思义,分享指针,相比上一个,它的原理就简单得多,首先接管一个对象,如果同时有多个对象一起管理,那就在这个对象的计数器上+1,在取消管理的时候计数器-1,如果为0,则没有对象需要管理,进行析构。

这里直接进行模拟实现,原理比较简单,就不再细说,看代码了解即可。

        shared_ptr(K* ptr):_ptr(ptr),_count(new int (1)){}
​~shared_ptr(){Release();}
​shared_ptr(const shared_ptr<K>& k1):_ptr(k1._ptr), _count(k1.count){(*_count)++;}
​shared_ptr operator=(const shared_ptr<K>& k1){if (k1._ptr != _ptr){Release();
​_ptr = k1._ptr;_count = k1._count;(*_count)++;}}
​K& operator&(){return *_ptr;}
​K* operator*(){return _ptr;}K* get(){
​return _ptr;}
​private:K* _ptr;int* _count;};

这里要注意的一点是:

shared_ptr并不是完全都是好的,比方说下面这种场景:

有一个双向链表的两个节点 K,K1

K的下一个节点是K1,也就是说现在K的计数应该为2。

K1的上一个节点是K,也就是说现在K1的计数也为2。

此时,如果我要析构K,K1,首先应该析构K,但是K的析构只会减一,因为它的地址还被K1保留,那我要析构就要先去析构K1,但是K1的节点也被K保留,就会出现循环引用导致报错。

为了解决这个问题,shared_ptr又加了一种指针——week_ptr,即弱指针,它使用的时候并不会将count++,也就解决了析构的时候出现的减不到零的情况。

模拟实现:

    template<class K>class weak_ptr{weak_ptr():_ptr(nullptr){}
​weak_ptr(const shared_ptr<K>& K1):_ptr(ptr){}
​weak_ptr operator(const shared_ptr<K>& K1){if (K1.get() != _ptr){_ptr = K1._ptr;}
​return *this;}
​K& operator&(){return *_ptr;}
​K* operator*(){return _ptr;}
​private:K* _ptr;};

这样就不会出现循环引用的问题,感谢观看,希望这篇文章能带你初步了解智能指针的思想和模拟实现。


相关文章:

【C++】智能指针思路解析和模拟实现

此篇文章就从以下几个方面出发&#xff0c;带你了解智能指针的方方面面1.为什么需要智能指针当我们开辟内存并使用的时候&#xff0c;我们的顺序应该是这样&#xff1a;开辟内存-》使用内存-》释放内存问题就出现在第三步&#xff0c;开辟好了&#xff0c;也使用了&#xff0c;…...

SpringCloud(18):Sentinel流控降级入门

Sentinel本地应用流控降级实现分为三步: 创建本地应用搭建本地Sentinel控制台本地应用接入本地Sentinel控制台1 本地应用创建 整体流程分析 创建springboot项目在项目的pom.xml文件中引入sentinel-core的依赖坐标创建TestController,定义使用限流规则运行测试具体流程 1.创…...

C++【多态】

文章目录1、多态的概念2、多态的定义及实现2-1、多态的构成条件2-2、虚函数2-3、虚函数的重写2-4 多态样例2-5、协变2-6、 析构函数与virtual2-7、函数重载、函数隐藏&#xff08;重定义&#xff09;与虚函数重写&#xff08;覆盖&#xff09;的对比2-8、override 和 final&…...

缓存预热、缓存雪崩、缓存击穿、缓存穿透,你真的了解吗?

缓存穿透、缓存击穿、缓存雪崩有什么区别&#xff0c;该如何解决&#xff1f; 1.缓存预热 1.1 问题描述 请求数量较高&#xff0c;大量的请求过来之后都需要去从缓存中获取数据&#xff0c;但是缓存中又没有&#xff0c;此时从数据库中查找数据然后将数据再存入缓存&#xf…...

【Java基础】018 -- 面向对象阶段项目上(拼图小游戏)

目录 拼图小游戏&#xff08;GUI&#xff09; 一、主界面分析 1、练习一&#xff1a;创建主界面1 2、练习二&#xff1a;创建主界面2&#xff08;JFrame&#xff09; 3、练习三&#xff1a;在游戏界面中添加菜单&#xff08;JMenuBar&#xff09; ①、菜单的制作 4、添加图片&a…...

【网络~】

网络一级目录二、socket套接字三、UDP数据报套接字四、TCP流套接字一级目录 1.局域网、广域网 2.IP地址是什么&#xff1f; IP地址是标识主机在网络上的地址 IP地址是如何组成的&#xff1f; 点分十进制&#xff0c;将32位分为四个部分&#xff0c;每个部分一个字节&#xff…...

手写JavaScript中的call、bind、apply方法

手写JavaScript中的call、bind、apply方法 call方法 call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。 function Product(name, price) {this.name name;this.price price; }function Food(name, price) {Product.call(this, name, price);t…...

JAVA练习46-将有序数组转换为二叉搜索树

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 2月10日练习内容 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、题目-…...

linux(centos7.6)docker

官方文档&#xff1a;https://docs.docker.com/engine/install/centos/1安装之前删除旧版本的docker2安装yum install-y yum-utils3配置yum源 不用官网的外国下载太慢 推荐阿里云yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.r…...

微信小程序滚动穿透问题

文章目录1、catchtouchmove"true"2、page-meta3、wx.setPageStyle做小程序的开发业务中&#xff0c;经常会使用弹窗&#xff0c;当弹窗里的内容过多时&#xff0c;要滚动查看&#xff0c;然后经常会遇到滚动弹窗&#xff0c;弹窗底下页面也跟着滚。解决思路&#xff…...

安全—06day

负载均衡反向代理下的webshell上传负载均衡负载均衡下webshell上传的四大难点难点一&#xff1a;需要在每一台节点的相同位置上传相同内容的webshell难点二&#xff1a;无法预测下一次请求是哪一台机器去执行难点三&#xff1a;当我们需要上传一些工具时&#xff0c;麻烦来了&a…...

PostgreSQL入门

PostgreSQL入门 简介 PostgreSQL是以加州大学伯克利分校计算机系开发的POSTGRES&#xff0c; 版本 4.2为基础的对象关系型数据库管理系统&#xff08;ORDBMS&#xff09; 支持大部分SQL标准并且提供了许多现代特性 复杂查询外键触发器可更新视图事务完整性多版本并发控制 …...

自媒体人都在用的免费音效素材网站

视频剪辑、自媒体人必备的剪辑音效素材网站&#xff0c;免费下载&#xff0c;建议收藏&#xff01; 1、菜鸟图库 音效素材下载_mp3音效大全 - 菜鸟图库 菜鸟图库是一个综合性素材网站&#xff0c;站内涵盖设计、图片、办公、视频、音效等素材。其中音效素材就有上千首&#xf…...

Java数据结构中二叉树的深度解析及常见OJ题

本篇文章讲述Java数据结构中关于二叉树相关知识及常见的二叉树OJ题做法讲解&#xff08;包含非递归遍历二叉树&#xff09; 目录 一、二叉树 1.1二叉树概念 1.2特殊的二叉树 1.3二叉树性质 1.4二叉树基本性质定理题 1.5二叉树遍历基本操作 1.6二叉树遍历的前中后非递归写法 1.7…...

算法顶级比赛汇总

可参赛的算法比赛 阿里云天池大数据竞赛 时间&#xff1a;每年各个季度很多类型都会出题&#xff08;比赛总时间大概为两个月&#xff09; 内容&#xff1a;各个类型的算法题都会出、奖金上万不等 形式&#xff1a;在线提交&#xff08;提交后在线检查结果&#xff09;、离线…...

Android MVI框架搭建与使用

MVI框架搭建与使用前言正文一、创建项目① 配置AndroidManifest.xml② 配置app的build.gradle二、网络请求① 生成数据类② 接口类③ 网络请求工具类三、意图与状态① 创建意图② 创建状态四、ViewModel① 创建存储库② 创建ViewModel③ 创建ViewModel工厂五、UI① 列表适配器②…...

第九节 使用设备树实现RGB 灯驱动

通过上一小节的学习&#xff0c;我们已经能够编写简单的设备树节点&#xff0c;并且使用常用的of 函数从设备树中获取我们想要的节点资源。这一小节我们带领大家使用设备树编写一个简单的RGB 灯驱动程序&#xff0c;加深对设备树的理解。 实验说明 本节实验使用到STM32MP1 开…...

Ubuntu 系统下Docker安装与使用

Ubuntu 系统下Docker安装与使用Docker安装与使用Docker安装安装环境准备工作系统要求卸载旧版本Ubuntu 14.04 可选内核模块Ubuntu 16.04 使用 APT 安装安装 Docker CE使用脚本自动安装启动 Docker CE建立 docker 用户组测试 Docker 是否安装正确镜像加速Docker使用拉取镜像创建…...

DHCP安全及防范

DHCP安全及防范DHCP面临的威胁DHCP饿死攻击仿冒DHCP Server攻击DHCP中间人攻击DHCP Snooping技术的出现DHCP Snooping防饿死攻击DHCP Snooping防止仿冒DHCP Server攻击DHCP Snooping防止中间人攻击DHCP Snooping防止仿冒DHCP报文攻击DHCP面临的威胁 网络攻击无处不在&#xff…...

【流畅的python】第一章 Python数据模型

文章目录第一章 Python 数据模型1.1 python风格的纸牌1.2 如何使用特殊方法-通过创建一个向量类的例子1.3 特殊方法汇总第一章 Python 数据模型 python最好的品质是一致性 python解释器碰到特殊句法时&#xff0c;会使用特殊方法去激活一些基本的对象操作 这些特殊的方法以两个…...

from文件突然全部变为类cs右击无法显示设计界面

右击也不显示查看设计器 工程文件 .csproj中将 <Compile Include"OperatorWindows\Connection.cs" /> <Compile Include"OperatorWindows\Connection.Designer.cs"> <DependentUpon>Connection.cs</DependentUpon> &…...

使用arthas中vmtool命令查看spring容器中对象的某个属性

场景&#xff1a; 线上环境我想查看spring中容器某个对象的属性值 vmtool命令 方式一&#xff1a; vmtool --action getInstances -c [类加载器的hash] --className [目标类全路径] --limit 10 -x 2 实例&#xff1a;查询该类的全部属性情况&#xff08;该类是一个spri…...

四种幂等性解决方案

什么是幂等性&#xff1f; 幂等是一个数学与计算机学概念&#xff0c;在数学中某一元运算为幂等时&#xff0c;其作用在任一元素两次后会和其作用一次的结果相同。 在计算机中编程中&#xff0c;一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。 幂等…...

【Nacos】Nacos配置中心客户端配置更新源码分析

上文我们说了服务启动的时候从远程Nacos服务端拉取配置&#xff0c;这节我们来说下Nacos服务端配置的变动怎么实时通知到客户端&#xff0c;首先需要注册监听器。 注册监听器 NacosContextRefresher类会监听应用启动发布的ApplicationReadyEvent事件&#xff0c;然后进行配置…...

按钮防抖与节流-vue2

防抖与节流&#xff0c;应用场景有很多&#xff0c;例如&#xff1a;禁止重复提交数据的场景、搜索框输入搜索条件&#xff0c;待输入停止后再开始搜索。 防抖 点击button按钮&#xff0c;设置定时器&#xff0c;在规定的时间内再次点击会重置定时器重新计时&#xff0c;在规定…...

PyTorch学习笔记:nn.SmoothL1Loss——平滑L1损失

PyTorch学习笔记&#xff1a;nn.SmoothL1Loss——平滑L1损失 torch.nn.SmoothL1Loss(size_averageNone, reduceNone, reductionmean, beta1.0)功能&#xff1a;创建一个平滑后的L1L_1L1​损失函数&#xff0c;即Smooth L1&#xff1a; l(x,y)L{l1,…,lN}Tl(x,y)L\{l_1,\dots,l…...

2年时间,涨薪20k,想拿高薪还真不能老老实实的工作...

2016年开始了我的测试生活。 2016年刚到公司的时候&#xff0c;我做的是测试工程师。做测试工程师是我对自己的职业规划。说实话&#xff0c;我能得到这份工作真的很高兴。 来公司的第一个星期&#xff0c;因为有一个项目缺人&#xff0c;所以部门经理提前结束了我的考核期&a…...

Spark - Spark SQL中RBO, CBO与AQE简单介绍

Spark SQL核心是Catalyst, Catalyst执行流程主要分4个阶段, 语句解析, 逻辑计划与优化, 物理计划与优化, 代码生成 前三个阶段都由Catalyst负责, 其中, 逻辑计划的优化采用RBO思路, 物理计划的优化采用CBO思路 RBO (Rule Based Optimization) 基于规则优化, 通过一系列预定好…...

NeurIPS/ICLR/ICML AI三大会国内高校和企业近年中稿量完整统计

点击文末公众号卡片&#xff0c;找对地方&#xff0c;轻松参会。 近日&#xff0c;有群友转发了一张网图&#xff0c;统计了近年来中国所有单位在NeurIPS、ICLR、ICML论文情况。原图如下&#xff1a; 中稿数100&#xff1a; 清华(1) 北大(2) 占比&#xff1a;22.6%。 累计数…...

Android IO 框架 Okio 的实现原理,到底哪里 OK?

本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 提问。 前言 大家好&#xff0c;我是小彭。 今天&#xff0c;我们来讨论一个 Square 开源的 I/O 框架 Okio&#xff0c;我们最开始接触到 Okio 框架还是源于 Square 家的 OkHttp 网络…...

怎么让别人看到自己做的网站/火狐搜索引擎

原文地址&#xff1a;https://blog.csdn.net/u011080472/article/details/51337422 多任务和高并发的内存交互...

如何做好网络营销管理/西安seo代运营

E此浏览器不支持画布C我一路 看 过 千山和万水C我的脚 踏 遍 天南和地北F 我都无所谓日晒或是风 吹F 鲜红的纯粹路边那朵蔷 薇C关掉了 手 机 管他谁是谁C不要去 理 会 是是与非非F 从不觉疲惫天亮走到天 黑F F C黄昏中的堡 垒 (多颓废)F G如果迎着风 就飞Em Am俯瞰这世界 有多美…...

网页设计基础教程视频教程/seo优化裤子关键词

qt中有时候使用new后并没有使用delete&#xff0c;原因是 Qt 自动回收是靠父子关系。父亲销毁了。他的孩子也销毁。 #include "mainwindow.h" #include <QApplication> #include <QTextCodec> #include <QLabel> int main(int argc, char *argv[…...

做最好的在线看片网站/东莞做网站seo

庆幸也与你逛过那一段旅程曾是日夜期待你施舍一点同情这算是固执做梦或太热情?在世上没有多少东西会尽如人意多数像讽刺逐年成长必经苦恋故事我爱你你扮作不知完了吧如无意外重今开始该好好恋爱放下从前一段感情才能追求将来你就似没存在完了吧仍能撑起来前进便让自尊心放开告…...

网站关键词排名/今日热搜榜

折纸王子帮你找折纸图解你好&#xff0c;我是折纸王子&#xff0c;欢迎来到我的公众号。折纸王子教你折纸&#xff0c;讲解详细&#xff0c;演示清楚&#xff0c;容易听懂&#xff0c;一学就会。往期精彩&#xff1a;圣诞节剪纸折纸大全43款万圣节折纸大全专辑 29款折纸张口霸王…...

平板电脑可以做网站吗/郑州网站建设方案

导读随着信息化技术的不断发展&#xff0c;整个社会对于信息化技术的依赖程度越来越高&#xff0c;在这种情况下&#xff0c;学习编程将对未来的工作和学习具有更多的实际意义。未来编程将不仅仅是程序员的事情&#xff0c;对于广大职场人来说&#xff0c;编程也将是一个重要的…...