C++——智能指针 auto_ptr

news2026/2/26 18:56:06

一、RAII思想的引入

#include <iostream>
using namespace std;


#if 0
// C++中动态申请的资源需要用户自己手动释放
// 如果操作不当,容易造成内存泄漏
// 能否做到让资源自动被释放:RAII
// RAII : 将资源交给对象管理,对象被销毁时自动调用析构函数可以在析构函数中将资源释放掉

template<class T>
class smart_ptr
{
public:
	smart_ptr(T* ptr = nullptr)
		: _ptr(ptr)
	{}

	// 具有指针类似的效果
	T& operator*()
	{
		return *_ptr;
	}

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

	~smart_ptr()
	{
		if (_ptr)
		{
			delete _ptr;
			_ptr = nullptr;
		}
	}

	T* Get()
	{
		return _ptr;
	}

private:
	T* _ptr;
};


void TestSmartPtr1()
{
	//int* p = new int(10);
	//smart_ptr<int> sp(p);

	// ...

	//delete p;


	smart_ptr<int> sp(new int(10));

	*sp = 100;
	// ...
}


struct A
{
	int a;
	int b;
	int c;
};

void TestSmartPtr2()
{
	smart_ptr<int> sp1(new int(10));
	*sp1 = 100;

	smart_ptr<A> sp2(new A());
	sp2->a = 10;
	sp2->b = 20;
	sp2->c = 30;
}


// 上述smart_ptr已经很好了,达到了刚开始的需求
// 新的问题:类中涉及到资源的管理时,如果没有显式实现拷贝构造 已经 赋值运算符重载
// 则编译器会以浅拷贝的方式实现,smart_ptr就会有问题
// 解决:能够深拷贝解决吗? 答案:不可以
int main()
{
	// TestSmartPtr1();
	TestSmartPtr2();
	return 0;
}
#endif

 二、对于memory库中auto_ptr的使用

// 智能指针:对原生态指针进行了封装,以类的方式管理用户的资源,在析构方法中将资源释放掉
// RAII + 具有指针类似的行为 + 如何解决浅拷贝的问题 
// 因此:解决深拷贝方式的不同,实现了不同版本的智能指针

// 第一种智能指针
// C++98 auto_ptr 原理:
// RAII + 具有指针类似的行为 + 资源转移来解决浅拷贝问题的
#include <memory>

#if 0
class A
{
public:
	A()
	{
		cout << "A::A()" << endl;
	}

	~A()
	{
		cout << "A::~A()" << endl;
	}

	int _a;
	int _b;
};


void TestAutoPtr()
{
	auto_ptr<A> ap1(new A());
	ap1->_a = 10;
	ap1->_b = 20;

	// 当ap1拷贝构造ap2时,ap1会将自己管理的资源
	// 转移给ap2,然后ap1不在管理了,即:指向空
	auto_ptr<A> ap2(ap1);
	ap2->_a = 100;
	ap2->_b = 200;

	// ap1->_a = 10;  // 运行崩溃:因为ap1将资源转移走之后指向NULL

	auto_ptr<A> ap3;

	// 当ap2给ap3赋值时,ap2会将自己管理的资源
	// 转移给ap3,然后ap2不在管理资源了,即:指向空
	ap3 = ap2;


	A* pa1 = new A();
	A* pa2 = nullptr;

	pa2 = pa1;
	pa1->_a = 10;
	pa2->_b = 20;
}

int main()
{
	TestAutoPtr();
	return 0;
}
#endif

 三、实现自己自己的auto_ptr

#if 0
namespace bite
{
	template<class T>
	class auto_ptr
	{
	public:
		// RAII
		auto_ptr(T* ptr = nullptr)
			: _ptr(ptr)
		{}

		~auto_ptr()
		{
			if (_ptr)
			{
				delete _ptr;
				_ptr = nullptr;
			}
		}

		// 具有指针类似的行为
		T& operator*()
		{
			return *_ptr;
		}

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

		// 资源转移
		auto_ptr(auto_ptr<T>& ap)
			: _ptr(ap._ptr)
		{
			ap._ptr = nullptr;  资源转移体现在对用来赋值的旧对象的指针置空
		} 

		auto_ptr<T>& operator=(auto_ptr<T>& ap)
		{
			if (this != &ap)
			{
				if (_ptr)     新对象指针有内容的话,需要先进行置空处理。
				{
					delete _ptr;
				}

				_ptr = ap._ptr;  利用旧对象指针给新对象指针赋值
				ap._ptr = nullptr; 同样是对旧对象的指针置空
			}

			return *this;
		}
	private:
		T* _ptr;
	};
}
#endif


 四、auto_ptr版本二:加入资源权限的转移

// C++98中auto_ptr的改造:
// RAII + 具有指针类似的行为 + 解决浅拷贝的方式:资管管理权限的转移
// 资管管理权限: 对资源释放的权限

namespace bite
{
	template<class T>
	class auto_ptr
	{
	public:
		// RAII
		auto_ptr(T* ptr = nullptr)
			: _ptr(ptr)
			, _owner(false)
		{
			if (_ptr)
			{
				_owner = true;
			}
		}

		~auto_ptr()
		{
			if (_ptr && _owner)
			{
				delete _ptr;
				_ptr = nullptr;
				_owner = false;
			}
		}

		// 具有指针类似的行为
		T& operator*()
		{
			return *_ptr;
		}

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

		// 资源转移
		auto_ptr(const auto_ptr<T>& ap)
			: _ptr(ap._ptr)
			, _owner(ap._owner)
		{
			ap._owner = false;
		}

		auto_ptr<T>& operator=(const auto_ptr<T>& ap)
		{
			if (this != &ap)
			{
				if (_ptr && _owner)
				{
					delete _ptr;
				}

				_ptr = ap._ptr;
				_owner = ap._owner;
				ap._owner = false;
			}

			return *this;
		}
	private:
		T* _ptr;
		mutable bool _owner;  // 如果为true,表明该对象具有释放资源的权限
	};
}

class A
{
public:
	A()
	{
		cout << "A::A()" << endl;
	}

	~A()
	{
		cout << "A::~A()" << endl;
	}

	int _a;
	int _b;
};


void TestAutoPtr1()
{
	bite::auto_ptr<A> ap1(new A());
	ap1->_a = 10;
	ap1->_b = 20;

	// 当ap1拷贝构造ap2时,ap1会将自己管理的资源
	// 转移给ap2,然后ap1不在管理了,即:指向空
	bite::auto_ptr<A> ap2(ap1);
	ap2->_a = 100;
	ap2->_b = 200;

	ap1->_a = 10;  // 运行成功

	bite::auto_ptr<A> ap3;

	// 当ap2给ap3赋值时,ap2会将自己管理的资源
	// 转移给ap3,然后ap2不在管理资源了,即:指向空
	ap3 = ap2;

	A* pa1 = new A();
	A* pa2 = nullptr;

	pa2 = pa1;
	pa1->_a = 10;
	pa2->_b = 20;
	delete pa1;
}

void TestAutoPtr2()
{
	bite::auto_ptr<A> ap1(new A());
	ap1->_a = 10;
	ap1->_b = 20;

	if (true)
	{
		bite::auto_ptr<A> ap2(ap1);
		ap1->_a = 100;
		ap2->_b = 200;
	}

	// 当if结束时,ap2,退出了自己的程序范围,调用析构函数,ap2将资源释放了
	// 因此ap1内部的指针就变成了野指针
	ap1->_a = 1000;
	ap1->_b = 2000;
}

// C++标准建议:在什么情况下都不要使用auto_ptr
int main()
{
	// TestAutoPtr1();
	TestAutoPtr2();
	return 0;
}

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

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

相关文章

性能优化之SSR、SSG

一、SSR和SSG介绍 SSR&#xff08;Server-Side Rendering&#xff0c;服务端渲染&#xff09;和 SSG&#xff08;Static Site Generation&#xff0c;静态站点生成&#xff09;是现代前端框架&#xff08;如 Next.js、Nuxt.js、Gatsby&#xff09;的核心渲染策略&#xff0c;用…

经典算法:回文链表

题目&#xff1a;234. 回文链表 给你一个单链表的头节点 head&#xff0c;请你判断该链表是否为 回文链表。如果是&#xff0c;返回 true&#xff1b;否则&#xff0c;返回 false。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示例 2&#x…

uboot移植之GPIO上电初始状态的调整

开发板在上电之后&#xff0c;GPIO都有一个默认初始状态&#xff0c;这个状态可能是高电平也可能是低电平。而我们的应用程序在正式接管控制这些GPIO&#xff0c;是在内核起来并成功加载根文件系统之后。所以在内核启动的这段时间内&#xff0c;这些GPIO保持在一种不受控的状态…

本地id_rsa.pub输入到服务器~/.ssh/authorized_keys后,依然需要输入密码的解决办法

首先检查服务器&#xff1a; sudo vim /etc/ssh/sshd_config 然后把这两个修改为&#xff1a; 如果依然需要输入密码&#xff0c;在本地终端&#xff1a; ssh -v userserver 查看认证过程&#xff0c;例如我这里提示说明客户端已成功尝试使用密钥认证&#xff1a; 进一步…

【设计模式-3.7】结构型——组合模式

说明&#xff1a;本文介绍结构型设计模式之一的组合模式 定义 组合模式&#xff08;Composite Pattern&#xff09;又叫作整体-部分&#xff08;Part-Whole&#xff09;模式&#xff0c;它的宗旨是通过将单个对象&#xff08;叶子节点&#xff09;和组合对象&#xff08;树枝…

Unity Mac 笔记本操作入门

在 macOS 笔记本电脑上使用 Unity Editor 的场景视图 (Scene View) 旋转视角&#xff0c;主要依赖于触摸板手势和键盘修饰键的组合。由于没有物理中键&#xff0c;操作方式会与 Windows 鼠标略有不同。 以下是具体的旋转视角操作&#xff1a; 1. 基本旋转视角 (Orbit) 这是最…

实时数据仓库是什么?数据仓库设计怎么做?

目录 一、实时数据仓库是什么 &#xff08;一&#xff09;实时数据仓库的定义 &#xff08;二&#xff09;实时数据仓库的特点 二、实时数据仓库的应用场景 &#xff08;一&#xff09;金融行业 &#xff08;二&#xff09;电商行业 &#xff08;三&#xff09;物联网行…

Linux(12)——基础IO(下)

目录 六、重定向 &#x1f4c4;输出重定向 &#x1f4c4;输入重定向 &#x1f4c4;追加重定向 &#x1f4c4;dup2 七、理解一切皆文件 八、缓冲区 &#x1f9e0;什么是缓冲区 &#x1f9e0;为什么要引入缓冲区 &#x1f4c4;缓冲区类型 九、FILE 六、重定向 我们这…

WPF可拖拽ListView

1.控件描述 WPF实现一个ListView控件Item子项可删除也可拖拽排序&#xff0c;效果如下图所示 2.实现代码 配合 WrapPanel 实现水平自动换行&#xff0c;并开启拖拽 <ListViewx:Name"listView"Grid.Row"1"Width"300"AllowDrop"True&…

[蓝桥杯]倍数问题

倍数问题 题目描述 众所周知&#xff0c;小葱同学擅长计算&#xff0c;尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况&#xff0c;当有很多个数之后就会比较苦恼。现在小葱给了你 nn 个数&#xff0c;希望你从这 nn 个数中找到三个数&#xff0c;使得…

【MySQL】 约束

一、约束的定义 MySQL 约束是用于限制表中数据的规则&#xff0c;确保数据的 准确性 和 一致性 。约束可以在创建表时定义&#xff0c;也可以在表创建后通过修改表结构添加。 二、常见的约束类型 2.1 NOT NULL 非空约束 加了非空约束的列不能为 NULL 值&#xff0c;如果可以…

前端vue打开多个窗口,关闭窗口后才继续执行后续逻辑

1.打开第一个弹窗 弹窗的按钮代码 2.点击窗口1中按钮&#xff0c;打开新的窗口 // 请领单按钮点击 async cb_6_delClick() {let ls_yfbm this.st_3Value.BMBMlet pstring {}pstring.a ls_yfbmpstring.b this.queryFormDialog.outDepotDeptCodeawait this.openwithparm_w_md…

「深度拆解」Spring Boot如何用DeepSeek重构MCP通信层?从线程模型到分布式推理的架构进化

什么是MCP&#xff1f; MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;是由Anthropic公司于2024年11月推出的开放标准协议&#xff0c;旨在为大型语言模型&#xff08;LLM&#xff09;与外部数据源、工具及系统提供统一的交互接口&#xff0c;被…

【西门子杯工业嵌入式-2-点亮一颗LED】

西门子杯工业嵌入式-2-点亮一颗LED 一、课程回顾与目标1.上节课内容回顾2.本节课目标 二、硬件连接与原理1. 硬件连接方式2. 连接实例 三、GPIO原理知识1. GPIO结构2. 推挽输出模式原理 四、软件实现步骤1. 项目结构设置2. 函数定义3. led.c 文件编写初始化函数 led_init交替闪…

代码随想录算法训练营第60期第五十五天打卡

大家好&#xff0c;我们今天继续我们图论的部分&#xff0c;其实我们昨天是主要讲解了深搜与广搜的理论基础&#xff0c;我们大体上了解了两种算法的差异与适用情景&#xff0c;今天我们就继续我们的图论的章节&#xff0c;以后几天的题目是图论中比较有名的问题叫做岛屿问题&a…

重磅更新! 基于Gemini 2.5 Pro打造的AI智能体PlantUML-X上线!

目录 图表绘制AI智能体PlantUML-X上线通过简单的提示词创建各种UML图&#xff1a;轻松搞定其它类型的技术图表&#xff1a; AI智能体PlantUML-X功能实测画一个在Java中的一个简单的用户登录功能的时序图效果展示&#xff1a;根据详细内容生成系统架构图效果展示&#xff1a;效果…

[5-02-04].第01节:Jmeter环境搭建:

JMeter笔记大纲 Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0c;并且配置了环境变量 一、JMeter概述&#xff1a; 1.1.JMeter是什么&#xff1a; JMeter是Appache组织使用java开发的一款测试工具 可以用于对服务器、网络或对象模拟巨大的负载…

AI智能推荐实战之RunnableParallel并行链

导读&#xff1a;在现代AI应用开发中&#xff0c;如何高效处理多维度数据分析始终是开发者面临的核心挑战。当您需要同时进行情感分析、关键词提取和实体识别&#xff0c;或者要对比多个AI模型的输出结果时&#xff0c;传统的串行处理方式往往效率低下。 本文将深入解析LangCha…

Gemini开源项目DeepResearch:基于LangGraph的智能研究代理技术原理与实现

引言 在人工智能快速发展的今天&#xff0c;如何构建一个能够进行深度研究、自主学习和迭代优化的AI系统成为了技术前沿的重要课题。Gemini开源的DeepResearch一周收获7.9k Star&#xff0c;Google的开源项目Gemini DeepResearch技术通过结合LangGraph框架和Gemini大语言模型&…

Doris Catalog 联邦分析查询性能优化:从排查到优化的完整指南

在大数据分析中&#xff0c;Doris 的 Catalog 联邦分析功能为整合多源数据提供了有力支持。然而&#xff0c;在实际应用中&#xff0c;可能会遇到各种问题影响其正常运行。本文将详细剖析这些问题并提供解决方案。 一、联邦分析查询慢&#xff1a;内外表通用排查逻辑 当遇到 …