C++进阶--智能指针

智能指针的概念

智能指针是C++中的一个重要概念,用于管理动态分配的对象内存它是一个类模板,通过封装原始指针,并在对象生命周期结束时自动释放内存,从而避免了内存泄漏和资源管理的繁琐工作

C++标准库提供了多种常见的智能指针,目前常用的有:unique_ptr , shared_ptr , weak_ptr。(头文件: < memory >

为什么需要智能指针?

看一个例子:

int div()
{int a, b;cin >> a >> b;if (b == 0)throw invalid_argument("除0错误");return a / b;
}
void Func()
{// 1、如果p1这里new 抛异常会如何?// 2、如果p2这里new 抛异常会如何?// 3、如果div调用这里又会抛异常会如何?int* p1 = new int;int* p2 = new int;cout << div() << endl;delete p1;delete p2;
}
int main()
{try{Func();}catch (exception& e){cout << e.what() << endl;}return 0;
}

在这里插入图片描述

RAll

RAII(Resource Acquisition Is Initialization)的核心思想是资源的获取和释放应该与对象的生命周期绑定在一起。当一个对象被创建时,它应该获取所需要的资源;当对象被销毁时,它应该释放已经获取的资源。这样可以确保资源在不再需要时被正确释放,从而避免资源泄漏。

利用RAll原理做出智能指针

代码:

template<class T>
class SmartPtr
{
public://RALLSmartPtr(T* ptr):_ptr(ptr){}~SmartPtr(){cout << "delete: " << _ptr<< endl;delete _ptr;}//解引用T& operator*(){return *_ptr;}//指针形式T* operator->(){return _ptr;}
private:T* _ptr;
};

利用RAll原理制作智能指针:
在这里插入图片描述
在这里插入图片描述

测试:在这里插入图片描述
在这里插入图片描述

auto_ptr

在这里插入图片描述

简单使用

在这里插入图片描述
在这里插入图片描述
由于这种智能指针不能对实际应用起到作用,所以现在大多数程序员都没有用到它。

要模拟实现一个auto_ptr时,只需要在上面代码的赋值拷贝中加上:
在这里插入图片描述

unique_ptr

unique_ptr与常规指针的一个主要区别就是:它拥有对指向对象的独占拥有权。这意味着同一时间只能有一个unique_ptr指向某个对象,不能进行复制操作,只能进行移动操作。当unique_ptr被销毁或重置时,他所指向的对象也会自动删除。

模拟实现

template<class T>class unique_ptr{public:unique_ptr(T* ptr):_ptr(ptr){}unique_ptr(unique_ptr<T>& p)= delete;unique_ptr operator=(const unique_ptr<T>& p) = delete;~unique_ptr(){cout << "delete:" << _ptr << endl;delete _ptr;}// 像指针一样T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};

实现时只需要对默认拷贝构造和默认赋值构造给它删除了,那么就实现了不能对它进行复制了。

测试:
在这里插入图片描述

shared_ptr

在这里插入图片描述

为什么不能用static成员来进行计数?

在这里插入图片描述

模拟实现

template<class T>class shared_ptr{public://常规使用的构造函数shared_ptr(T* ptr = nullptr): _ptr(ptr),_count(new int(1)){}//sp2(sp1)shared_ptr(const shared_ptr<T>& sp){_ptr = sp._ptr;_count = sp._count;//拷贝后将count+1++(*_count);}//sp3=sp1shared_ptr<T>& operator=(const shared_ptr<T>& sp){if (_ptr != sp._ptr){//使用赋值时,要考虑之前的智能指针指向的空间release();_ptr = sp._ptr;_count = sp._count;//拷贝后将count+1++(*_count);}return *this;}//释放资源void release(){if (--(*_count) == 0){cout << "delete:" << _ptr << endl;delete _ptr;delete _count;}}~shared_ptr(){//当count为0时触发release();}int use_count(){return *_count;}// 像指针一样T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T* get() const{return _ptr;}private:T* _ptr;int* _count;};

解释:
在这里插入图片描述

测试:
在这里插入图片描述

赋值时必须要对之前智能指针指向的空间进行检查:
在这里插入图片描述

验证解引用:
在这里插入图片描述

定制删除器

在这里插入图片描述
在类中添加一个成员:
在这里插入图片描述
在这里插入图片描述
添加一个构造函数的重载:
在这里插入图片描述
在这里插入图片描述
释放时的修改:
在这里插入图片描述

template <class T>
struct ArrayDelete
{void operator()(T* ptr){delete[] ptr;}
};
//定制删除器
int main()
{fnc::shared_ptr<ListNode> n(new ListNode(10));fnc::shared_ptr<ListNode> n1(new ListNode[10],ArrayDelete<ListNode>());fnc::shared_ptr<FILE> n2(fopen("FileName.cpp", "r"), [](FILE* file) {fclose(file); });
}

在这里插入图片描述

智能指针的缺陷

struct ListNode
{int _val;fnc::shared_ptr<ListNode> _next;fnc::shared_ptr<ListNode> _prev;ListNode(int val=0):_val(val){}
};int main()
{fnc::shared_ptr<ListNode> n1(new ListNode(10));fnc::shared_ptr<ListNode> n2(new ListNode(20));cout << n1.use_count() << endl;cout << n2.use_count() << endl;n1->_next = n2;n2->_prev = n1;cout << n1.use_count() << endl;cout << n2.use_count() << endl;//delete n1;//delete n2;return 0;
}

结果:
在这里插入图片描述
在这里插入图片描述

weak_ptr

weak_ptr就是用于解决循环引用的问题。它与shared_ptr配合使用,可以指向一个由shared_ptr管理的对象,但不会增加该对象的引用计数。

weak_ptr不拥有所指对象的拥有权,当指向对象被释放时,weak_ptr会自动失效,不再指向有效的对象

	template<class T>class weak_ptr{public:// RAllweak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptr<T>& sp){_ptr = sp.get();}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}// 像指针一样T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};

将LIstNode的next指针和prev指针类型改为weak_ptr的:
在这里插入图片描述
结果:
在这里插入图片描述

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

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

相关文章

CasinoRoyale靶机练习实践报告

CasinoRoyale靶机练习实践报告 下载地址: https://drive.google.com/open?id1FYP246L63zShV00wOckAQ5F5XJ4HkZ0Lhttps://download.vulnhub.com/casinoroyale/CasinoRoyale.ovahttps://download.vulnhub.com/casinoroyale/CasinoRoyale.ova.torrent ( Magnet) 1 安装靶机 …

【Java Spring MVC项目异常解决】HTTP 500

HTTP 500状态码表示“内部服务器错误”&#xff08;Internal Server Error&#xff09;。这是一个通用的错误响应&#xff0c;表明服务器在处理请求时遇到了预料之外的情况&#xff0c;导致无法完成请求。500错误是服务器端错误的一种&#xff0c;与客户端无关。在Web开发中&am…

强化SSH服务安全的最佳实践

SSH&#xff08;Secure Shell&#xff09;作为一种广泛应用于Linux和其他类Unix系统中的强大工具&#xff0c;为管理员提供了安全的远程登录和命令执行功能。在现今高度互联的网络环境中&#xff0c;确保SSH服务的安全性显得尤为重要。本文将详细阐述一系列SSH服务的最佳实践&a…

【LangChain系列 12】Prompt模版——序列化

本文速读&#xff1a; PromptTemplate FewShotPromptTemplate 通常prompt以文件形式存储比python代码更好&#xff0c;一方面可以更容易共享、存储。本文将介绍在LangChain中如何对prompt以不同的方式序列化。 一般来说&#xff0c;对于序列化有以下两个设计原则&#xff1a…

吴恩达机器学习笔记:第 8 周-13 聚类(Clustering)13.3-13.5

目录 第 8 周 13、 聚类(Clustering)13.3 优化目标13.4 随机初始化13.5 选择聚类数 第 8 周 13、 聚类(Clustering) 13.3 优化目标 K-均值最小化问题&#xff0c;是要最小化所有的数据点与其所关联的聚类中心点之间的距离之和&#xff0c;因此 K-均值的代价函数&#xff08;又…

《微信公众号开发---一站式开发流程完整版本》 测试公众号账号及本地环境搭建/验证本地编写的代码,接入微信指南请求测试正常

文章目录 目录 文章目录 安装流程 小结 概要安装流程技术细节小结 概要 1.准备工作 1.需要先登录微信公众号平台&#xff1a;微信公众平台 注册如果是公司开发请注册服务号&#xff0c;个人开发请注册订阅号 2.注册完成&#xff0c;需要开通认证 2.以上操作完成&#xff0c…

通信原理(2)--随机过程

通信原理(2)–随机过程 3.1随机过程的基本概念 随机过程{x(t)}由一族时间函数 x i ( t ) x_i(t) xi​(t)&#xff0c;i1,2.3…组成&#xff0c;每一个时间函数 x i ( t ) x_i(t) xi​(t)称为随机过程{x(t)}的一个样本函数&#xff08;一个实现&#xff09; 每个样本函数在时间…

ASP.NET某企业信息管理系统的设计与实现

摘 要 信息管理系统就是我们常说的MIS(Management Information System),它是一个计算机软硬件资源以及数据库的人-机系统。经过对题目和内容的分析,选用了Microsoft公司的ASP.NET开发工具,由于它提供了用于从数据库中访问数据的强大工具集,使用它可以建立开发比较完善的数据库…

《2024年绿色发展报告》:算力与电力矛盾愈加突出!

2024年4月22日&#xff0c;第55个世界地球日&#xff0c;超聚变发布《2024年绿色发展报告》&#xff0c;向社会展示超聚变面对宏观形势变化、产业趋势变化&#xff0c;推进绿色发展、科技向绿的探索与实践成果。 2023年&#xff0c;算力产业发生了深刻变化。大模型带来AI算力需…

Git如何配合Github使用

1.安装Git https://git-scm.com/ ##2.配置 Git 安装完成后&#xff0c;你需要设置 Git 的用户名和邮箱地址&#xff0c;这样在提交代码时就能知道是谁提交的。你可以在命令行中输入以下命令来配置&#xff1a; git config --global user.name "Your Name" git con…

探索UTONMOS《神念无界-源起山海》元宇宙游戏的奇幻世界

在科技的前沿&#xff0c;元宇宙游戏如同一扇神秘的大门&#xff0c;缓缓开启&#xff0c;引领我们进入一个前所未有的奇幻世界。 UTONMOS《神念无界-源起山海》元宇宙游戏是数字世界的巅峰之作&#xff0c;它打破了现实与虚拟的界限&#xff0c;让玩家能够身临其境地体验各种奇…

U盘格式转换GPT格式转回DOS

当前格式 fdisk /dev/sdb# 在 fdisk 提示符下&#xff0c;输入以下命令删除分区&#xff1a; d # 选择要删除的分区编号&#xff08;如 1、2 等&#xff09; w开始转换 [rootnode-24 ~]# fdisk /dev/sdbWelcome to fdisk (util-linux 2.37.4). Changes will remain in memory o…

[笔试训练](八)

目录 022&#xff1a;求最小公倍数 023&#xff1a;数组中的最长连续子序列 024&#xff1a;字母收集 022&#xff1a;求最小公倍数 求最小公倍数_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 求最小公倍数公式&#xff1a;lcm(a,b)a*b/gcd(a,b)&am…

Android使用ProtoBuf 适配 gradle7.5 gradle8.0

ProtoBuf 适配 Gradle7.5 gradle-wrapper.properties 配置 distributionUrlhttps\://services.gradle.org/distributions/gradle-7.5-bin.zipProject&#xff1a;build.gradle: plugins {id com.android.application version 7.4.2 apply falseid com.android.library versio…

星尘智能 AI 机器人 S1——国产机器人的巅峰之作

AI智能机器人真的太炸裂了 国产科技威武-CSDN直播AI智能机器人真的太炸裂了 国产科技威武https://live.csdn.net/v/382519 最近发现了一个国产的机器人&#xff0c;真的让人惊叹不已&#xff01;它就是星尘智能 AI 机器人 S1&#xff01; 这个机器人简直太牛逼了&#xff01;…

elaticsearch windows安装

es下载地址 https://www.elastic.co/cn/downloads/elasticsearch https://www.elastic.co/cn/downloads/past-releases#elasticsearch 在这里插入图片描述 下载直接解压&#xff0c;解压后目录 双击bin目录下的elasticsearch.bat开启服务 注意&#xff1a;9300 端口为 Elas…

03 spring-boot+mybatis+jsp 的增删改查的入门级项目

前言 主要是来自于 朋友的需求 项目概况 就是一个 用户信息的增删改查然后 具体到业务这边 使用 mybatis xml 来配置的增删改查 后端这边 springboot mybatis mysql fastjson 的一个基础的增删改查的学习项目, 简单容易上手 前端这边 jsp 的 基础的试题的增删改查 学习项…

Android使用AlertDialog实现弹出菜单

最近又开始捣鼓APP&#xff0c;许多api , class都忘记怎么用了&#xff0c;楼下使用AlertDialog实现个弹出菜单&#xff0c;结果直接crash&#xff0c;查了半天&#xff0c;终于即将&#xff0c;记录一下…… 1 实现代码 AlertDialog.Builder mBuilder new AlertDialog.Builde…

MySQL B+索引的工作原理及应用

引言 在数据库系统中&#xff0c;索引是优化查询、提高性能的关键技术之一。特别是在MySQL数据库中&#xff0c;B树索引作为最常用的索引类型&#xff0c;对数据库性能有着至关重要的影响。本文旨简单解析MySQL中B树索引的工作原理&#xff0c;帮助学生朋友们更好地理解和利用…

微信小程序实时日志使用,setFilterMsg用法

实时日志 背景 为帮助小程序开发者快捷地排查小程序漏洞、定位问题&#xff0c;我们推出了实时日志功能。开发者可通过提供的接口打印日志&#xff0c;日志汇聚并实时上报到小程序后台。开发者可从We分析“性能质量->实时日志->小程序日志”进入小程序端日志查询页面&am…