聊聊 C++ 中的几种智能指针 (上)

一:背景

我们知道 C++ 是手工管理内存的分配和释放,对应的操作符就是 new/deletenew[] / delete[],  这给了程序员极大的自由度也给了我们极高的门槛,弄不好就得内存泄露,比如下面的代码:

void test() {int* i = new int(10);*i = 10;
}int main() {test();
}

这段代码因为用了 new 而忘了 delete,导致在 nt heap 上分配的 i 随着栈地址的回收而成了一块孤悬海外的内存占用,所以修正后的代码如下:

void test() {int* i = new int(10);*i = 10;delete i;
}int main() {test();
}

但这种写法比较麻烦,智者千虑必有一失,总会有忘记加 delete 的时候,那怎么办呢?大家应该知道内存自动管理有两种手段。

  1. 引用计数

代表作有 Python,PHP,还有 windows 的句柄管理。

  1. 引用跟踪

代表作有 C#,JAVA 等一众工程化语言。

因为 引用计数 实现比较简单,主要就是记录下对象的引用次数,次数为 0 则释放,所以可完全借助 类的构造函数析构函数栈的自动回收特性 弄一个简单的 引用计数 ,对应着如下四个关键词。

  1. auto_ptr

  2. shared_ptr

  3. unique_ptr

  4. weak_ptr

接下来我们逐个聊一聊。

二:关键词解析

1. auto_ptr

这是 C++ 最早出现一个的 简单引用计数法,参考代码如下:

void test() {auto_ptr<int> ptr = auto_ptr<int>(new int(10));
}int main() {test();
}

接下来看下汇编代码:

auto_ptr<int> ptr = auto_ptr<int>(new int(10));
...
00771D26  call        std::auto_ptr<int>::auto_ptr<int> (07710FAh)  
00771D2B  lea         ecx,[ebp-0D8h]  
00771D31  call        std::auto_ptr<int>::~auto_ptr<int> (0771159h)

可以看到,它分别调用了 构造函数析构函数,接下来找下 auto_ptr 这两个函数的源码。

class auto_ptr {private:_Ty* _Myptr; // the wrapped object pointerpublic:auto_ptr(auto_ptr_ref<_Ty> _Right) noexcept {_Ty* _Ptr = _Right._Ref;_Right._Ref = nullptr; // release old_Myptr = _Ptr; // reset this}~auto_ptr() noexcept {delete _Myptr;}
}

源码一看就明白了,在构造函数中,将 new int 的地址塞给了内部的 _Myptr 指针,在析构函数中对 _Myptr 进行 delete ,真好,这样就不用整天担心有没有加 delete 啦。

值得注意的是,现在 C++ 不推荐这个了,而是建议使用新增的:shared_ptr,unique_ptr,weak_ptr, 怎么说呢?auto_ptr 有一个不好处理的问题,就是现实开发中会出现这么个场景,多个 ptr 指向同一个 引用,如下图:

bd312945729f9c9a41804082254878ac.png

2. auto_ptr 多引用问题

  1. 方式1:

定义三个 ptr,然后包装同一个 new int 地址,参考代码如下:

void test() {int* i = new int(10);auto_ptr<int> ptr1(i);auto_ptr<int> ptr2(i);auto_ptr<int> ptr3(i);
}

这种写法有没有问题呢?肯定有问题啦,还记得 auto_ptr 的析构是 delete 吗?对同一块内存多次 delete 会抛异常的,如下图所示:

eddfde7361223bce7be140c6cdd221ae.png
  1. 方式2:

既然定义三个有问题, 那就用赋值运算符= 让 ptr1,ptr2,ptr3 指向同一个地址是不是就可以啦?参考代码如下:

void test() {int* i = new int(10);auto_ptr<int> ptr1(i);auto_ptr<int> ptr2 = ptr1;auto_ptr<int> ptr3 = ptr2;
}int main() {test();
}

那这段代码有没有问题呢?有没有问题得要看 = 运算符是如何重写的😪,扒一下源码看看。

template <class _Other>
auto_ptr& operator=(auto_ptr<_Other>& _Right) noexcept {reset(_Right.release());return *this;
}
_Ty* release() noexcept {_Ty* _Tmp = _Myptr;_Myptr = nullptr;return _Tmp;
}

从源码看有一个很恶心的点,他会将 _Right 下的 _Myptr 设为 nullptr,也就是说此时的 ptr1 报废了,言外之意就是后续再访问 ptr1 会抛 访问违例

13e75b6539acdf666452d28a36777fea.png

哈哈,C++里面的专业术语叫 控制权转移

好了,本篇就说这么多吧,下一篇聊聊新增的这些关键词,看看如何将 auto_ptr 更合理的分权。

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

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

相关文章

【Android 学习】深入理解Handler机制

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请注明出处http://blog.csdn.net/u013132758。 https://blog.csdn.net/u013132758/article/details/51355051 Android 提供了Handler和Looper来来满足线程间的通信&#xff0c;而前面我们所说的IPC指的是进程间的通信。…

【QGIS入门实战精品教程】4.3:QGIS属性表按字段链接外部属性数据

属性数据是GIS空格数据的重要组成部分。属性数据采集的基本操作由于地理实体(如建筑物) 位于地块之内成者与地块有关(如道路),因此,描述地理实体的属性数据和描述地块实体与地理实体之间关系的属性数强大多数都是土地信息的范畴土地空间数据库的属性教据主要是用来描述空间目…

解决 Cmder 的光标跟文字有个间距 及常用配置

具体的方法&#xff1a; 菜单 > SettingStartup > Environment set PATH%ConEmuBaseDir%\Scripts;%PATH% set LANGzh_CN.UTF8 chcp 65001 如果无效&#xff1a;在 Cmder 下的 verndor 目录里&#xff0c;修改 clink.lua 文件大约40和46行&#xff0c;把符号 λ 改为 # …

做一个高德地图的 iOS / Android .NET MAUI 控件系列 - 创建控件

我们知道 MAUI 是开发跨平台应用的解决方案 &#xff0c;用 C# 可以直接把 iOS , Android , Windows , macOS , Linux ,Tizen 等应用开发出来。那我们在这个框架除了用底层自定义的 UI 控件外&#xff0c;如果我们要用如高德地图这样的第三方控件&#xff0c;要如何做呢&#x…

flask中的session,render_template()第二和参数是字典

1. 设置一个secret_key 2.验证登入后加上session,这是最简单,不保险 . 3.注意render_template传的参数是字典 转载于:https://www.cnblogs.com/cuzz/p/8087844.html

失败记录两则

一&#xff0c;未找出为什么有的CPU应用超高&#xff0c;而另一些CPU静静啥也不干。可能是将JOB的优先级设置低了&#xff1f; 二&#xff0c;给BOSS的三星I9300线刷港版ROM失败。可能文件坏&#xff0c;最可能数据线不是原装&#xff1f;

【QGIS入门实战精品教程】1.1:QGIS与GIS的区别和联系

「刘一哥GIS」系列专栏《QGIS入门实战精品教程(配套案例数据)》目录 1. QGIS概述 QGIS(在2.0版本之前称之为Quantum GIS)于2002年由Gary Sherman创立,在2007年由OSGeo接管,并于2009年发布了1.0版本,目前最高版本为3.22。QGIS采用开源证书GNU GPLv2 (GNU General Public…

简单的对拍

在算法竞赛中&#xff0c;我们常用对拍来初步检验程序。 网上也有其它的关于对拍的教程&#xff0c;但是任性的我还是要自己写一篇教程。  首先&#xff0c;我们要知道我们是用一个叫做” 批处理文件&#xff08;.bat&#xff09;“的东西来处理这个问题。点击初步了解bat 不过…

AI 之 OpenCvSharp 大图找小图(案例版)

要说跟AI扯上啥关系&#xff0c;估计只有库本身了&#xff0c;但是&#xff0c;这个大图搜小图功能还是不错的&#xff0c;有喜欢的可以试试。我主要用的场景是&#xff0c;具体的某个界面为大图&#xff0c;界面的某个图标为小图&#xff0c;或者&#xff0c;整个桌面为大图&a…

SaaS应用的十二要素

简介 如今&#xff0c;软件通常会作为一种服务来交付&#xff0c;它们被称为网络应用程序&#xff0c;或软件即服务&#xff08;SaaS&#xff09;。12-Factor 为构建如下的 SaaS 应用提供了方法论&#xff1a; 使用标准化流程自动配置&#xff0c;从而使新的开发者花费最少的…

路由器与交换机区别

路由器与交换机区别 近日&#xff0c;在回答知道网友提问的时候&#xff0c;发现很多朋友不知道路由器与交换机的不同&#xff0c;常常问一些看起来有点可笑的问题。比如路由器同时登陆两个账号&#xff0c;所以今天写下这篇经验&#xff0c;科普一下路由器的功能和交换机的功能…

【QGIS入门实战精品教程】1.2:QGIS与ArcGIS的区别和联系

「刘一哥GIS」系列专栏《QGIS入门实战精品教程(配套案例数据)》目录 以下是GISGeography官方给出的两者之间的27点比较(译): 官方网址:https://gisgeography.com/qgis-arcgis-differences/ 1.QGIS容纳更多的数据格式 ArcGIS没有支持所有的数据格式,毫无疑问,QGIS在处…

押注.NET 是件好事

作者 | Bryan Costanich译者 | 明知山策划 | 褚杏娟作为一个在.NET 上构建了不止一个流行平台的人&#xff0c;我经常被问到它的相关性&#xff0c;以及它是不是一个值得投入的生态系统。这个问题在旧金山湾区的技术世界里尤为流行&#xff0c;这里的技术潮流就像四季一样变更交…

8-12 canvas专题-阶段练习一(上)

8-12 canvas专题-阶段练习一&#xff08;上&#xff09; 1 <!DOCTYPE html>2 <html lang"zh-cn">3 <head>4 <meta charset"UTF-8">5 <title>8-12 课堂演示</title>6 </head>7 <style type"text…

【QGIS入门实战精品教程】2.2:QGIS软件的下载与安装(Windows)

文章目录 一、QGIS下载二、QGIS安装​一、QGIS下载 QGIS软件官网下载地址:https://www.qgis.org/en/site/ 进入官网之后,点击【Download Now】进入下载页面: 选择对应的版本进行下载: 开始下载:

Linux sudo找不到命令:修改sudo的PATH路径

为什么80%的码农都做不了架构师&#xff1f;>>> sudo有时候会出现找不到命令&#xff0c;而明明PATH路径下包含该命令&#xff0c;让人疑惑。其实出现这种情况的原因&#xff0c;主要是因为当 sudo以管理权限执行命令的时候&#xff0c;linux将PATH环境变量进行了重…

快速判断站点是否存活的 3 种编程实现

前言如何知道外部站点是否正在运行&#xff1f;如果使用浏览器&#xff0c;直接访问对应站点即可。那么&#xff0c;使用 C# 以编程方式&#xff0c;如何实现呢&#xff1f;GET 请求首先想到的&#xff0c;就是使用 HttpClient 向该站点发送 HTTP 请求&#xff0c;并检查返回状…

【数据结构与算法】拓扑排序问题C语言实现

拓扑排序是有向无环图的一种应用,在实际生活中用的很多。 比如GIS专业的课程设计,许多课程需要前置课程要求,也就是说没上过A课程、则不可能直接去学B课程,画个图表就是: 同理,我们教材中的范例:穿衣服的过程也是一个拓扑排序问题,如下表: 有关这个拓扑排序的模型构造…

[转]2020年排名前20的基于SpringBoot搭建的开源项目,帮你快速进行项目搭建!

△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 287 篇原创分享 作者 l Hollis 来源 l Hollis&#xff08;ID&#xff1a;hollischuang&#xff09; SpringBoot一直是开发者比较青睐的一款轻量级框架&#xff0c;他不仅继承了Spring框架原有的优秀特性&#xff0c;而…

C# 搭建一个基于.NET5的WPF入门项目

概述.NET5 发布已经有一阵子了&#xff0c;今天抽空体验一哈&#xff0c;搭建一个WPF项目实例&#xff0c;看看和传统的.NET Framework有什么区别&#xff01;开发环境&#xff1a;VS2019 WPF框架&#xff1a;Caliburn.Micro 版本4.0.173.NET版本&#xff1a;.NET5.0项目创建步…