【Happy!1024】C++智能指针

news2024/9/29 21:19:07

🍎 博客主页:🌙@披星戴月的贾维斯
🍎 欢迎关注:👍点赞🍃收藏🔥留言
🍇系列专栏:🌙 C/C++专栏
🌙请不要相信胜利就像山坡上的蒲公英一样唾手可得,但是请相信,世界上总有一些美好值得我们全力以赴,哪怕粉身碎骨!🌙
🍉一起加油,去追寻、去成为更好的自己!

在这里插入图片描述

文章目录

  • 前言
  • 🍎1.为什么需要智能指针?
  • 🍎2.内存泄漏
  • 🍎3.智能指针的使用及原理
  • 🍎总结

提示:以下是本篇文章正文内容,下面案例可供参考


前言

    先祝所有程序猿1024快乐!!!这次和大家分享一些智能指针的知识以及传值杯的一些有意思的题目,希望大家读了能有所收获!

🍎1.为什么需要智能指针?

    C++这门语言有着悠久的历史,C++有非常多优点,执行效率高,可以直接操作内存和指针, 许多我们现在看到的现象级软件,如windows的部分是C++ 写的,但是C++有一个比较大的缺点就是容易写着写着就内存泄漏了,即使是许多比较优秀的程序猿,如果没有注意,也可能会犯下这个错误,所以就有人去研究了智能指针,来解决这方面的问题。

🍎2.内存泄漏

2.1 什么是内存泄漏,内存泄漏的危害

   什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费

内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

参考下面代码

void TestMemory()
{
    //1.内存申请了忘记释放
    int *p1 = (int*)malloc(sizeof(int));
    int *p2 = new int;
    
    // 2.异常安全问题
    int* p3 = new int[10];
 
    Func(); // 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放.
 
    delete[] p3;
}

2.2 内存泄漏分类
我们主要关心两种方面的内存泄漏:

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

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

2.3如何避免内存泄漏

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

🍎3.智能指针的使用及原理

3.1 什么是RAII
RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内
存、文件句柄、网络连接、互斥量等等)的简单技术。

在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在
对象析构的时候释放资源
。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做
法有两大好处:

  1. 不需要显式地释放资源。
  2. 采用这种方式,对象所需的资源在其生命期内始终保持有效。
// 使用RAII思想设计的SmartPtr类
template<class T>
class SmartPtr {
public:
    SmartPtr(T* ptr = nullptr)
       : _ptr(ptr)
   {}
    ~SmartPtr()
   {
        if(_ptr)
            delete _ptr;
   }
    
private:
    T* _ptr;
};

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

template<class T>
	class SmartPtr
	{
	public:
		// RAII思想
		SmartPtr(T* ptr)
			:_ptr(ptr)
		{}

		~SmartPtr()
		{
			cout <<"delete"<<_ptr << endl;
			//delete[] _ptr;
			delete _ptr;
			_ptr = nullptr;
		}

		// 像指针一样
		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

		T* Get()
		{
			return _ptr;
		}
	private:
		T* _ptr;
	};

总结一下智能指针的原理:

  1. RAII特性
  2. 重载operator*和opertaor->,具有像指针一样的行为。

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

template<class T>
	class auto_ptr
	{
	public:
		// RAII思想
		auto_ptr(T* ptr)
			:_ptr(ptr)
		{}

		~auto_ptr()
		{
			if (_ptr)
			{
				cout << "delete" << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
			}
		}

		// sp2(sp1)
		auto_ptr(auto_ptr<T>& sp)
			:_ptr(sp._ptr)
		{
			sp._ptr = nullptr;
		}

		// ...

		// 像指针一样
		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

		T* get()
		{
			return _ptr;
		}
	private:
		T* _ptr;
	};

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

// C++11库才更新智能指针实现
// C++11出来之前,boost搞除了更好用的scoped_ptr/shared_ptr/weak_ptr
// C++11将boost库中智能指针精华部分吸收了过来
// C++11->unique_ptr/shared_ptr/weak_ptr
// unique_ptr/scoped_ptr
// 原理:简单粗暴 -- 防拷贝
template<class T>
	class unique_ptr
	{
	public:
		// RAII思想
		unique_ptr(T* ptr)
			:_ptr(ptr)
		{}

		~unique_ptr()
		{
			if (_ptr)
			{
				cout << "delete" << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
			}
		}

		// 像指针一样
		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

		T* get()
		{
			return _ptr;
		}


	//private:
	//	// sp2(sp1)
	//	// C++98
	//	// 1、只声明,不实现
	//	// 2、声明成私有
	//	unique_ptr(const unique_ptr<T>& sp);

		unique_ptr(const unique_ptr<T>& sp) = delete;
		unique_ptr<T>& operator=(const unique_ptr<T>& sp) = delete;

	private:
		T* _ptr;
	};

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

  1. shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。
  2. 在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。
  3. 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
  4. 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对
    象就成野指针了。
// 引用计数支持多个拷贝管理同一个资源,最后一个析构对象释放资源
template<class T>
	class shared_ptr
	{
	public:
		void Release()
		{
			if (--(*_pCount) == 0 && _ptr)
			{
				cout << "delete" << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;

				delete _pCount;
				_pCount = nullptr;
			}
		}

		// RAII思想
		shared_ptr(T* ptr)
			:_ptr(ptr)
			, _pCount(new int(1))
		{}

		~shared_ptr()
		{
			Release();
		}

		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			, _pCount(sp._pCount)
		{
			(*_pCount)++;
		}

		

		// sp1 = sp3
		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			//if (this != &sp)
			if (_ptr != sp._ptr)
			{
				Release();

				_ptr = sp._ptr;
				_pCount = sp._pCount;
				++(*_pCount);
			}

			return *this;
		}


		// 像指针一样
		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

		T* get()
		{
			return _ptr;
		}

	private:
		T* _ptr;
		int* _pCount;
	};
}

关于shared_ptr的几个问题:

  1. shared_ptr智能指针是线程安全的吗?
    是的,引用计数的加减是加锁保护的。但是指向资源不是线程安全的。指向堆上资源的线程安全问题是访问的人处理的,智能指针不管,也管不了。引用计数的线程安全问题,是智能指针要处理的
  2. shared_ptr的线程安全问题(我们留到下节再讲解)

🍎总结

    本文和大家介绍了智能指针相关的几个问题,下节我们详细聊聊shared_ptr的线程安全问题,以及循环引用之类的知识点,希望对大家有所帮助!

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

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

相关文章

【计算摄像学】博资考

TOC 本博客将覆盖的内容&#xff1a; 数字相机&#xff08;Digital Camera&#xff09; 小孔成像模型&#xff08;pinhole imaging model&#xff09; 如下图所示&#xff0c;物体反射的光线射向四面八方&#xff0c;直接使用传感器无法直接得到物体形貌。 小孔成像模型在传…

Spring中AOP详解

目录 一、AOP的概念 二、AOP的底层实现原理 2.1 JDK的动态代理 2.1.1 invocationhandler接口 2.1.2 代理对象和原始类实现相同的接口 interfaces 2.1.3 类加载器ClassLoador 2.1.4 编码实现 2.2 Cglib动态代理 2.2.1 Cglib动态代理编码实现 三、AOP如何通过原始对象的id获取到代…

PCL入门1之点云读取及可视化

0 引言 本文主要记录在Ubuntu系统的PCL点云库安装过程&#xff0c;以及PCL点云读取和可视化的c代码示例。 1 PCL安装 本文是安装了pcl1.8大版本&#xff0c;可先下载 下载pcl 1.8.1 版本&#xff08;点击Source code(zip&#xff09; 先安装pcl1.8.1所需的依赖库&#xff1…

【在英伟达nvidia的jetson-orin-nx和PC电脑ubuntu20.04上-装配ESP32开发调试环境-基础测试】

【在英伟达nvidia的jetson-orin-nx和PC电脑ubuntu20.04上-装配ESP32开发调试环境-基础测试】 1、概述2、实验环境3、 物品说明4、参考资料与自我总结5、实验过程1、创建目录2、克隆下载文件3、 拉取子目录安装和交叉编译工具链等其他工具4、添加环境变量6、将样例文件拷贝到桌面…

使用el-tree问题之清空勾数据不生效

一、问题场景描述 在做角色菜单按钮权限时&#xff0c;多数采用树结构勾选数据&#xff0c;这里使用了element中的el-tree。如下图&#xff1a; 1、我给角色1勾选了权限列表数据的前三行&#xff0c; 点击弹框的确定 2、紧接着点击角色2的权限按钮&#xff0c;给角色2分配修…

Lvs +keepalivede : 高可用集群

keepalived为Ivs应运而生的高可用服务。Ivs的调度器无法做高可用&#xff0c;于是keepalived这个软件。 实现的是调度器的高可用。 但是: keepalived不是专为Ivs集群服务的&#xff0c;也可以做其他代理服务器的高可用。 lvs的高可用集群&#xff1a;主调度器和备调度器&#…

[springboot源码分析]-Conditional

https://www.baeldung.com/spring-conditional-annotations Condition元数据 1 org.springframework.context.annotation.Conditional 1.1Conditional定义 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented public interface…

区块链技术在现代商业中的应用:打造透明与信任的新经济体系

区块链技术以其独特的不可篡改和去中心化特点&#xff0c;在全球范围内受到了广泛的关注和讨论。从金融、供应链管理到版权保护和身份验证&#xff0c;区块链技术正在逐步改变着传统商业运营模式&#xff0c;为企业和消费者带来更加透明、安全和高效的商业环境。本文将深入探讨…

计算机网络第一章笔记

b站深入浅出计算机网络 微课视频 第一章 概述 因特网概述 区别&#xff1a; 若干节点和链路互连形成网络若干网络通过路由器互连形成互连网&#xff08;互联网&#xff09;因特网是当今世界上最大的互联网 发展的三个阶段&#xff1a; 1969年&#xff0c;第一个分组交换网…

MQTT协议和边缘计算

1.基本概念 MQTT是基于TCP/IP协议栈构建的异步通信消息协议&#xff0c;是一种轻量级的发布、订阅信息传输协议。可以在不可靠的网络环境中进行扩展&#xff0c;适用于设备硬件存储空间或网络带宽有限的场景。使用MQTT协议&#xff0c;消息发送者与接收者不受时间和空间的限制…

【AI视野·今日CV 计算机视觉论文速览 第273期】Mon, 23 Oct 2023

AI视野今日CS.CV 计算机视觉论文速览 Mon, 23 Oct 2023 Totally 73 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Using Human-like Mechanism to Weaken Effect of Pre-training Weight Bias in Face-Recognition Convolutional Neural N…

力扣每日一题62:不同路径

题目描述&#xff1a; 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1f; 示例 1&#xff1a; 输入&#xff1a;m 3, n 7 输出&#xff1a;28 示例 2&#xff…

《红蓝攻防对抗实战》八.利用OpenSSL对反弹shell流量进行加密

前文推荐&#xff1a; 《红蓝攻防对抗实战》一. 隧道穿透技术详解《红蓝攻防对抗实战》二.内网探测协议出网之TCP/UDP协议探测出网《红蓝攻防对抗实战》三.内网探测协议出网之HTTP/HTTPS协议探测出网《红蓝攻防对抗实战》四.内网探测协议出网之ICMP协议探测出网《红蓝攻防对抗…

cmp云管平台专业厂商哪家好?有什么优势?

企业上云后&#xff0c;使用CMP云管平台就至关重要了&#xff0c;不仅方便云管理&#xff0c;还能节约云成本&#xff0c;还能保障云资源安全。但很多小伙伴不知道cmp云管平台专业厂商哪家好&#xff1f;有什么优势&#xff1f;这里就简单回答一下。 cmp云管平台专业厂商哪家好…

【QT】其他常用控件2

新建项目 lineEdit 什么都不显示&#xff08;linux password&#xff09; password textEdit和plainTextEdit spinBox和doubleSpinBox timeEdit、dateEdit、dateTimeEdit label 显示图案&#xff0c;导入资源&#xff1a;【QT】资源文件导入_复制其他项目中的文件到qt项目中_St…

医学图像分割利器:U-Net网络详解及实战

1 U-Net网络介绍 1.1 U-Net由来 2015年U-Net的出现使得原先需要数千个带注释的数据才能进行训练的深度学习神经网络大大减少了训练所需要的数据量&#xff0c;并且其针对神经网络在图像分割上的应用开创了先河。当时神经网络在图像分类任务上已经有了较好的成果&#xff0c;但…

出现了一个全新的编程语言——Mojo

最近&#xff0c;编程领域又一个黑马忽然冲进了开发者们的视野并正式开放下载。 Mojo 的简介 Mojo是一种新推出的编程语言&#xff0c;它将Python的简单性与Rust的速度和内存安全性结合在一起。 它处于开发的早期阶段&#xff0c;为用户提供了一个在线游乐场来探索其功能。 …

【JAVA学习笔记】 30 - Object类详解(equal,hashCode,toString)

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter08/src/com/yinhai/object_ 一、equal方法 和equal的对比 1.既可以判断基本类型&#xff0c;又可以判断引用类型&#xff0c;返回boolean值 2. 如果判断基本类型&#xff0c;判断的值是否相…

Vue 项目进行 SEO 优化

SSR 服务器渲染 服务端渲染, 在服务端 html 页面节点, 已经解析创建完了, 浏览器直接拿到的是解析完成的页面解构 关于服务器渲染&#xff1a;Vue 官网介绍 &#xff0c;对 Vue 版本有要求&#xff0c;对服务器也有一定要求&#xff0c;需要支持 nodejs 环境。 优势: 更好的 …

Mysql视图特性用户管理

目录 一、视图基本使用 二、用户管理 2.1 用户 ①用户信息 ②创建用户 tips:(解决无法创建用户) ③删除用户 ④修改用户密码 2.2数据库的权限 ①给用户授权 ②回收权限 视图&#xff1a;视图是一种虚拟表。视图是基于一个或多个基础表中的数据所创建的一个查询结果…