C++ 详谈智能指针的使⽤及其原理(一)

智能指针的使用及其原理(沉淀中) 本文介绍了C++智能指针的使用场景及其设计原理。在传统代码中,内存资源管理常因异常抛出导致泄漏问题,通过异常捕获处理虽可解决但代码繁琐。智能指针基于RAII(资源获取即初始化)思想,将资源托管给对象,利用对象生命周期自动管理资源释放。 文章对比了四种标准库智能指针:auto_ptr(已废弃)、unique_ptr(禁止拷贝)、shared_ptr(引用计数)和weak_ptr(解决循环引用)。重点说明了shared_ptr的拷贝特性及make_shared构造方式,并强调智能指针默认使用delete释放资源 阅读详情

目录

1. 智能指针的使⽤场景分析

2. RAII和智能指针的设计思路

3. C++标准库智能指针的使⽤

4. 智能指针的原理


1. 智能指针的使⽤场景分析

下⾯程序中我们可以看到,new了以后,我们也delete了,但是因为抛异常导,后⾯的delete没有得到执⾏,所以就内存泄漏了,所以我们需要new以后捕获异常,捕获到异常后delete内存,再把异常抛出,但是因为new本⾝也可能抛异常,连续的两个new和下⾯的Divide都可能会抛异常,让我们处理起来很⿇烦。智能指针放到这样的场景⾥⾯就让问题简单多了。

double Divide(int a, int b)
{
	// 当b == 0时抛出异常
	if (b == 0)
	{
		throw "Divide by zero condition!";
	}
	else
	{
		return (double)a / (double)b;
	}
}
void Func()
{
	// 这⾥可以看到如果发⽣除0错误抛出异常,另外下⾯的array和array2没有得到释放。
	// 所以这⾥捕获异常后并不处理异常,异常还是交给外⾯处理,这⾥捕获了再重新抛出去。
	// 但是如果array2new的时候抛异常呢,就还需要套⼀层捕获释放逻辑,这⾥更好解决⽅案
	// 是智能指针,否则代码太戳了
	int* array1 = new int[10];
	int* array2 = new int[10]; // 抛异常呢
	try
	{
		int len, time;
		cin >> len >> time;
		cout << Divide(len, time) << endl;
	}
	catch (...)
	{
		cout << "delete []" << array1 << endl;
		cout << "delete []" << array2 << endl;
		delete[] array1;
		delete[] array2;
		throw; // 异常重新抛出,捕获到什么抛出什么
	}
	// ...
	cout << "delete []" << array1 << endl;
	delete[] array1;
	cout << "delete []" << array2 << endl;
	delete[] array2;
}
int main()
{
	try
	{
		Func();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}
	catch (const exception& e)
	{
		cout << e.what() << endl;
	}
	catch (...)
	{
		cout << "未知异常" << endl;
	}
	return 0;
}

2. RAII和智能指针的设计思路

RAII是Resource Acquisition Is Initialization的缩写,他是⼀种管理资源的类的设计思想,本质是⼀种利⽤对象⽣命周期来管理获取到的动态资源,避免资源泄漏,这⾥的资源可以是内存、⽂件指针、⽹络连接、互斥锁等等。RAII在获取资源时把资源委托给⼀个对象,接着控制对资源的访问,资源在对象的⽣命周期内始终保持有效,最后在对象析构的时候释放资源,这样保障了资源的正常释放,避免资源泄漏问题。

智能指针类除了满⾜RAII的设计思路,还要⽅便资源的访问,所以智能指针类还会想迭代器类⼀样,重载 operator*/operator->/operator[] 等运算符,⽅便访问资源。

template<class T>
class SmartPtr
{
public:
	// RAII
	SmartPtr(T* ptr)
		:_ptr(ptr)
	{}
	~SmartPtr()
	{
		cout << "delete[] " << _ptr << endl;
		delete[] _ptr;
	}
	// 重载运算符,模拟指针的⾏为,⽅便访问资源
	T& operator*()
	{
		return *_ptr;
	}
	T* operator->()
	{
		return _ptr;
	}
	T& operator[](size_t i)
	{
		return _ptr[i];
	}
private:
	T* _ptr;
};
double Divide(int a, int b)
{
	// 当b == 0时抛出异常
	if (b == 0)
	{
		throw "Divide by zero condition!";
	}
	else
	{
		return (double)a / (double)b;
	}
}
void Func()
{
	// 这⾥使⽤RAII的智能指针类管理new出来的数组以后,程序简单多了
	SmartPtr<int> sp1 = new int[10];
	SmartPtr<int> sp2 = new int[10];
	for (size_t i = 0; i < 10; i++)
	{
		sp1[i] = sp2[i] = i;
	}
	int len, time;
	cin >> len >> time;
	cout << Divide(len, time) << endl;
}
int main()
{
	try
	{
		Func();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}
	catch (const exception& e)
	{
		cout << e.what() << endl;
	}
	catch (...)
	{
		cout << "未知异常" << endl;
	}
	return 0;
}

3. C++标准库智能指针的使⽤

C++标准库中的智能指针都在<memory>这个头⽂件下⾯,我们包含<memory>就可以是使⽤了,智能指针有好⼏种,除了weak_ptr他们都符合RAII和像指针⼀样访问的⾏为,原理上⽽⾔主要是解决智能指针拷⻉时的思路不同。

auto_ptr是C++98时设计出来的智能指针,他的特点是拷⻉时把被拷⻉对象的资源的管理权转移给拷⻉对象,这是⼀个⾮常糟糕的设计,因为他会到被拷⻉对象悬空,访问报错的问题,C++11设计出新的智能指针后,强烈建议不要使⽤auto_ptr。其他C++11出来之前很多公司也是明令禁⽌使⽤这个智能指针的。

unique_ptr是C++11设计出来的智能指针,他的名字翻译出来是唯⼀指针,他的特点的不⽀持拷⻉,只⽀持移动。如果不需要拷⻉的场景就⾮常建议使⽤他。

shared_ptr是C++11设计出来的智能指针,他的名字翻译出来是共享指针,他的特点是⽀持拷⻉,也⽀持移动。如果需要拷⻉的场景就需要使⽤他了。底层是⽤引⽤计数的⽅式实现的。

weak_ptr是C++11设计出来的智能指针,他的名字翻译出来是弱指针,他完全不同于上⾯的智能指针,他不⽀持RAII,也就意味着不能⽤它直接管理资源,weak_ptr的产⽣本质是要解决shared_ptr的⼀个循环引⽤导致内存泄漏的问题。具体细节下⾯我们再细讲。

智能指针析构时默认是进⾏delete释放资源,这也就意味着如果不是new出来的资源,交给智能指针管理,析构时就会崩溃。智能指针⽀持在构造时给⼀个删除器,所谓删除器本质就是⼀个可调⽤对象,这个可调⽤对象中实现你想要的释放资源的⽅式,当构造智能指针时,给了定制的删除器,在智能指针析构时就会调⽤删除器去释放资源。因为new[]经常使⽤,所以为了简洁⼀点,unique_ptr和shared_ptr都特化了⼀份[]的版本,使⽤时 unique_ptr<Date[]> up1(new Date[5]);shared_ptr<Date[]> sp1(new Date[5]); 就可以管理new []的资源。

template <class T, class... Args> shared_ptr<T> make_shared(Args&&... args);

shared_ptr 除了⽀持⽤指向资源的指针构造,还⽀持 make_shared ⽤初始化资源对象的值直接构造。

shared_ptr 和 unique_ptr 都⽀持了operator bool的类型转换,如果智能指针对象是⼀个空对象没有管理资源,则返回false,否则返回true,意味着我们可以直接把智能指针对象给if判断是否为空。

shared_ptr 和 unique_ptr 都得构造函数都使⽤explicit 修饰,防⽌普通指针隐式类型转换成智能指针对象。

struct Date
{
	int _year;
	int _month;
	int _day;
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}
	~Date()
	{
		cout << "~Date()" << endl;
	}
};
int main()
{
	auto_ptr<Date> ap1(new Date);
	// 拷⻉时,管理权限转移,被拷⻉对象ap1悬空
	auto_ptr<Date> ap2(ap1);
	// 空指针访问,ap1对象已经悬空
	//ap1->_year++;
	unique_ptr<Date> up1(new Date);
	// 不⽀持拷⻉
	//unique_ptr<Date> up2(up1);
	// ⽀持移动,但是移动后up1也悬空,所以使⽤移动要谨慎
	unique_ptr<Date> up3(move(up1));
	shared_ptr<Date> sp1(new Date);
	// ⽀持拷⻉
	shared_ptr<Date> sp2(sp1);
	shared_ptr<Date> sp3(sp2);
	cout << sp1.use_count() << endl;
	sp1->_year++;
	cout << sp1->_year << endl;
	cout << sp2->_year << endl;
	cout << sp3->_year << endl;
	// ⽀持移动,但是移动后sp1也悬空,所以使⽤移动要谨慎
	shared_ptr<Date> sp4(move(sp1));
	return 0;
}
template<class T>
void DeleteArrayFunc(T* ptr)
{
	delete[] ptr;
}
template<class T>
class DeleteArray
{
public:
	void operator()(T* ptr)
	{
		delete[] ptr;
	}
};
class Fclose
{
public:
	void operator()(FILE* ptr)
	{
		cout << "fclose:" << ptr << endl;
		fclose(ptr);
	}
};
int main()
{
	// 这样实现程序会崩溃
	// unique_ptr<Date> up1(new Date[10]);
	// shared_ptr<Date> sp1(new Date[10]);
	// 解决⽅案1
	// 因为new[]经常使⽤,所以unique_ptr和shared_ptr
	// 实现了⼀个特化版本,这个特化版本析构时⽤的delete[]
	unique_ptr<Date[]> up1(new Date[5]);
	shared_ptr<Date[]> sp1(new Date[5]);
	// 解决⽅案2
	// 仿函数对象做删除器
	//unique_ptr<Date, DeleteArray<Date>> up2(new Date[5], DeleteArray<Date>
	());
	// unique_ptr和shared_ptr⽀持删除器的⽅式有所不同
	// unique_ptr是在类模板参数⽀持的,shared_ptr是构造函数参数⽀持的
	// 这⾥没有使⽤相同的⽅式还是挺坑的
	// 使⽤仿函数unique_ptr可以不在构造函数传递,因为仿函数类型构造的对象直接就可以调⽤
	// 但是下⾯的函数指针和lambda的类型不可以
	unique_ptr<Date, DeleteArray<Date>> up2(new Date[5]);
	shared_ptr<Date> sp2(new Date[5], DeleteArray<Date>());
	// 函数指针做删除器
	unique_ptr<Date, void(*)(Date*)> up3(new Date[5], DeleteArrayFunc<Date>);
	shared_ptr<Date> sp3(new Date[5], DeleteArrayFunc<Date>);
	// lambda表达式做删除器
	auto delArrOBJ = [](Date* ptr) {delete[] ptr; };
	unique_ptr<Date, decltype(delArrOBJ)> up4(new Date[5], delArrOBJ);
	shared_ptr<Date> sp4(new Date[5], delArrOBJ);
	// 实现其他资源管理的删除器
	shared_ptr<FILE> sp5(fopen("Test.cpp", "r"), Fclose());
	shared_ptr<FILE> sp6(fopen("Test.cpp", "r"), [](FILE* ptr) {
		cout << "fclose:" << ptr << endl;
		fclose(ptr);
		});
	return 0;
}

4. 智能指针的原理

下⾯我们模拟实现了auto_ptr和unique_ptr的核⼼功能,这两个智能指针的实现⽐较简单,⼤家了解⼀下原理即可。auto_ptr的思路是拷⻉时转移资源管理权给被拷⻉对象,这种思路是不被认可的,也不建议使⽤。unique_ptr的思路是不⽀持拷⻉。

⼤家重点要看看shared_ptr是如何设计的,尤其是引⽤计数的设计,主要这⾥⼀份资源就需要⼀个引⽤计数,所以引⽤计数才⽤静态成员的⽅式是⽆法实现的,要使⽤堆上动态开辟的⽅式,构造智能指针对象时来⼀份资源,就要new⼀个引⽤计数出来。多个shared_ptr指向资源时就++引⽤计数,shared_ptr对象析构时就--引⽤计数,引⽤计数减到0时代表当前析构的shared_ptr是最后⼀个管理资源的对象,则析构资源。

namespace yzk
{
	template<class T>
	class auto_ptr
	{
	public:
		auto_ptr(T* ptr)
			:_ptr(ptr)
		{}
		auto_ptr(auto_ptr<T>& sp)
			:_ptr(sp._ptr)
		{
			// 管理权转移
			sp._ptr = nullptr;
		}
		auto_ptr<T>& operator=(auto_ptr<T>& ap)
		{
			// 检测是否为⾃⼰给⾃⼰赋值
			if (this != &ap)
			{
				// 释放当前对象中资源
				if (_ptr)
					delete _ptr;
				// 转移ap中资源到当前对象中
				_ptr = ap._ptr;
				ap._ptr = NULL;
			}
			return *this;
		}
		~auto_ptr()
		{
			if (_ptr)
			{
				cout << "delete:" << _ptr << endl;
				delete _ptr;
			}
		}
		// 像指针⼀样使⽤
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
	};
	template<class T>
	class unique_ptr
	{
	public:
		explicit unique_ptr(T* ptr)
			:_ptr(ptr)
		{}
		~unique_ptr()
		{
			if (_ptr)
			{
				cout << "delete:" << _ptr << endl;
				delete _ptr;
			}
		}
		// 像指针⼀样使⽤
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
		unique_ptr(const unique_ptr<T>&sp) = delete;
		unique_ptr<T>& operator=(const unique_ptr<T>&sp) = delete;
		unique_ptr(unique_ptr<T> && sp)
			:_ptr(sp._ptr)
		{
			sp._ptr = nullptr;
		}
		unique_ptr<T>& operator=(unique_ptr<T> && sp)
		{
			delete _ptr;
			_ptr = sp._ptr;
			sp._ptr = nullptr;
		}
	private:
		T* _ptr;
	};
	template<class T>
	class shared_ptr
	{
	public:
		explicit shared_ptr(T* ptr = nullptr)
			: _ptr(ptr)
			, _pcount(new int(1))
		{}
		template<class D>
		shared_ptr(T* ptr, D del)
			: _ptr(ptr)
			, _pcount(new int(1))
			, _del(del)
		{}
		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			, _pcount(sp._pcount)
			, _del(sp._del)
		{
			++(*_pcount);
		}
		void release()
		{
			if (--(*_pcount) == 0)
			{
				// 最后⼀个管理的对象,释放资源
				_del(_ptr);
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}
		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			if (_ptr != sp._ptr)
			{
				release();
				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
				_del = sp._del;
			}
			return *this;
		}
		~shared_ptr()
		{
			release();
		}
		T* get() const
		{
			return _ptr;
		}
		int use_count() const
		{
			return *_pcount;
		}
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
		int* _pcount;
		//atomic<int>* _pcount;
		function<void(T*)> _del = [](T* ptr) {delete ptr; };
	};
	// 需要注意的是我们这⾥实现的shared_ptr和weak_ptr都是以最简洁的⽅式实现的,
	// 只能满⾜基本的功能,这⾥的weak_ptr lock等功能是⽆法实现的,想要实现就要
	// 把shared_ptr和weak_ptr⼀起改了,把引⽤计数拿出来放到⼀个单独类型,shared_ptr
	// 和weak_ptr都要存储指向这个类的对象才能实现,有兴趣可以去翻翻源代码
	template<class T>
	class weak_ptr
	{
	public:
		weak_ptr()
		{}
		weak_ptr(const shared_ptr<T>& sp)
			:_ptr(sp.get())
		{}
		weak_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			_ptr = sp.get();
			return *this;
		}
	private:
		T* _ptr = nullptr;
	};
}
int main()
{
	yzk::auto_ptr<Date> ap1(new Date);
	// 拷⻉时,管理权限转移,被拷⻉对象ap1悬空
	yzk::auto_ptr<Date> ap2(ap1);
	// 空指针访问,ap1对象已经悬空
	//ap1->_year++;
	yzk::unique_ptr<Date> up1(new Date);
	// 不⽀持拷⻉
	//unique_ptr<Date> up2(up1);
	// ⽀持移动,但是移动后up1也悬空,所以使⽤移动要谨慎
	yzk::unique_ptr<Date> up3(move(up1));
	yzk::shared_ptr<Date> sp1(new Date);
	// ⽀持拷⻉
	yzk::shared_ptr<Date> sp2(sp1);
	yzk::shared_ptr<Date> sp3(sp2);
	cout << sp1.use_count() << endl;
	sp1->_year++;
	cout << sp1->_year << endl;
	cout << sp2->_year << endl;
	cout << sp3->_year << endl;
	return 0;
}

HTML5期末大作业:水果超市网站设计——水果超市(6页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 网购商城设置网页 HTML5期末大作业:水果超市网站设计——水果超市(6页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 网购商城设置网页 常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 明星、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 军事、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他 等网页设计题目, A+水平作业, 可满足大 阅读详情

相关推荐

新手必看|HDevelop核心算子快速上手,为C#移植打基础

在上一篇文章中,我们完成了C#+HALCON的开发环境搭建。但在实际工业开发中,绝不会直接在C#中编写视觉算法HDevelop可视化调试算法 → 验证效果 → 导出C#代码 → 集成到上位机。HDevelop是HALCON专属的算法调试工具,支持实时预览图像、参数动态调节、零编译运行,是新手入门和工业算法调试的核心工具。本文聚焦工业场景高频使用的核心算子,从基础操作到实战案例,手把手教你使用HDevelop;同时重点讲解算法导出C#的规范,让你调试完成的算法,能无缝移植到WinForm上位机中。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 777

【C++进阶】智能指针的使用及原理(1)

这篇文章介绍了智能指针的相关知识,下篇我们继续讨论智能指针,欢迎评论交流!

2402_82689232的博客 659

国产FPGA开发实战:紫光同创编程软件中的约束文件详解与常见问题

本文详细解析了紫光同创FPGA编程软件中约束文件的关键配置技巧与常见问题。通过基础架构解析、时钟约束实践、物理约束调控及典型问题排查指南,帮助开发者高效掌握国产FPGA开发中的约束文件应用,提升开发效率与设计稳定性。

gin88的博客 903

ado 利用智能指针进行数据库操作

在CaboutDlg头文件中定义两个ADO智能指针类实例,并在对话框中加入一个ListCtrl。        _ConnectionPtr m_pConnection;        _RecordsetPtr m_pRecordset;      ClistCtrl m_List;    ADO库包含三个智能指针:_ConnectionPtr、_CommandPtr和_Recordse

wxqian25的专栏 1491

零外围电路!用CH340X实现ESP32一键下载的完整教程

本文详细介绍了如何利用CH340X系列USB转串口芯片实现ESP32的一键自动下载功能,无需任何外围逻辑控制电路。通过解析CH340X的增强型DTR/RTS功能,提供核心电路设计、电压匹配方案,并指导在Arduino IDE和PlatformIO中进行软件配置,帮助开发者构建简洁、可靠且低成本的ESP32下载方案。

gpu4optimizer的博客 771

一份针对零基础学习AI Agent详细学习计划

以下是针对零基础学习者制定的AI Agent详细学习计划,结合最新行业动态和实用资源推荐,帮助你从入门到进阶系统掌握核心技能

sexy19910923的博客 1904

智能指针的种类以及使用场景

智能指针的种类以及使用场景

weixin_53492721的博客 2167

华为OD新系统机试真题 - 配置操作失败数量统计

华为OD机试新系统 4月8号【配置操作失败数量统计】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【配置操作失败数量统计】。

qq_45776114的博客 1158

C++学习之旅【智能指针的使⽤及其原理】

本文详细讲解了C++智能指针的使用场景、设计原理及实现方法。首先通过一个内存泄漏案例展示了裸指针管理的痛点,引出智能指针的必要性。随后深入剖析RAII(资源获取即初始化)的设计思想,这是智能指针的核心理论基础。文章重点介绍了智能指针类的实现方式:通过构造函数获取资源、析构函数自动释放资源,并重载运算符模拟指针行为。最后给出了一个完整的智能指针模板类实现代码,展示了如何用RAII机制自动管理动态内存,确保资源安全释放。全文从实际问题出发,逐步拆解智能指针的设计思路,帮助开发者掌握这一C++内存管理的核心工具。

承于所学,探技术之渊;以代码求政,寻成长之道。 1099

高速信号设计中的关键测试项目与测试仪器详解

高速信号设计是一个多维度协同优化的系统工程。时域分析如同外科手术刀般精准定位物理缺陷,频域分析提供传输通道的频谱指纹,信号质量评估量化系统鲁棒性,接收端容限测试验证极端工况下的可靠性,协议一致性确保生态互操作性,而电源完整性则直指诸多信号问题的根源。

u014344410的博客 217

北斗导航 | ChatGPT之RTK、RTD、ARAIM算法原理及程序代码(ChatGPT看你怎么回答,附部分代码)

ChatGPT之RTK、RTD、ARAIM算法原理及程序代码

尘世冰封的专栏 3677

【C++进阶】智能指针的使用及其原理

本文介绍了C++智能指针的使用场景、设计思路及标准库实现。主要内容包括: 通过异常处理案例展示内存泄漏问题,说明智能指针的必要性; 提出RAII(资源获取即初始化)设计思想,利用对象生命周期管理资源; 设计简易智能指针类,实现资源自动释放和指针行为模拟; 分析智能指针拷贝问题,对比标准库的auto_ptr、unique_ptr等解决方案; 重点指出auto_ptr存在管理权转移缺陷,建议避免使用。 文章通过代码示例和图示,系统讲解了智能指针如何解决资源泄漏问题,并比较了不同智能指针的实现特点。

Linux、C++、图形软件开发等。不一定每次都能写出完美的代码,但会认真搞懂每一个问题。 7376

为何wait和notify方法必须加锁?

为何wait和notify方法必须加锁? 是为了避免Lost Wake Up问题,即丢失唤醒问题。 所谓Lost Wake Up,指的是:线程A调用wait()方法进入阻塞状态,接下来没有其他线程去唤醒线程A,或者其他线程唤醒的时机不对(早于线程A的wait()),导致线程A永远阻塞下去。 下面以一个生产者和消费者的案例来说明上述问题。 假如我们有两个线程,一个消费者线程,一个生产者线程。生产者线程的任务可以简化成将count加一,而后唤醒消费者;消费者则是将count减一,而后在减到0的时候陷入睡眠,.

打酱油的葫芦娃 9155

c++解决常见内存泄漏问题——智能指针的使用及其原理

在c/c++程序的开发中,一些项目需要向内存手动申请空间,而手动申请的空间在我们不用时,必须手动将其释放,先不说我们其他问题,这种特有的机制,容易让我们手动向内存申请空间而忘记释放的问题。再说其他问题,如某个局部函数内部申请了资源,在它的栈帧销毁之前抛出了异常,此局部函数立即被终止了,而我们申请的资源也没有释放,这就导致了内存泄漏。所以有人提出能否把我们申请的资源交给一个对象来管理,如果我们忘记释放资源让这个对象来释放。

qq_58761784的博客 6122

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

C++11 智能指针的使⽤及其原理

本文深入探讨了C++智能指针的使用与原理。主要内容包括:1)智能指针的应用场景,通过RAII机制解决异常处理中的内存泄漏问题;2)标准库智能指针(auto_ptr/unique_ptr/shared_ptr/weak_ptr)的特性与使用差异,着重分析shared_ptr的引用计数机制;3)循环引用问题及weak_ptr的解决方案;4)shared_ptr的线程安全问题;5)内存泄漏的危害及防范措施。文章通过代码示例详细演示了各类智能指针的实现原理,并比较了不同智能指针的适用场景,为C++开发者提供了全面的

FirstForst的博客 871

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

智能指针的使⽤及其原理

我们想到赋值,可能就会这样直接写一个赋值,就是把你=右边的_ptr和pcount都给我然后再++即可,这样是错误的,因为你赋值是给一个已经存在的对象赋值的,所以,你需要赋值的这个对象可能就他自己指向一块空间,此时你让它指向别处,此时不就出现内存 泄漏了吗,所以还要判断一下。我们这样设计一下,就是使用一下指针,开辟一块空间只存放我们的这个引用计数的值,每次创建一个对象,就开辟一个空间存放它的值,如果你通过拷贝构造创建对象的话,此时就让我的这个引用计数这个指针指向你的引用计数指针的那块地址,然后再++即可。

shajjs的博客 769

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

【C++】智能指针的使用及其原理

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使⽤的内存,⼀般是忘记释 放或者发⽣异常释放程序未能执⾏导致的。内存泄漏并不是指内存在物理上的消失,⽽是应⽤程序分 配某段内存后,因为设计错误,失去了对该段内存的控制,因⽽造成了内存的浪费。内存泄漏的危害:普通程序运⾏⼀会就结束了出现内存泄漏问题也不⼤,进程正常结束,⻚表的映射 关系解除,物理内存也可以释放。

2301_78724721的博客 1294

C++ 智能指针的使⽤及其原理(包含模拟实现)

函数用途operator=共享所有权swap()交换指针reset()释放资源get()获取裸指针operator*->访问对象查看引用数unique()是否唯一判空所有权排序unique_ptr函数用途operator=转移所有权(仅支持移动赋值,拷贝被禁用)swap()交换两个unique_ptr的内部指针(高效,不涉及资源复制)reset()释放当前管理的对象,并可接管新对象(安全重置)get()获取原始裸指针(用于兼容 C 接口,不可 delete)operator*->

Fcy648的博客 883

【C++详解】C++ 智能指针:使用场景、实现原理与内存泄漏防治

C++ 智能指针:使用场景、实现原理与内存泄漏防治

2501_90265152的博客 2302

智能指针--C++

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存,一般是忘记释放或者发生异常释放程序未能执行导致的。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏的危害:普通程序运行一会就结束了出现内存泄漏问题也不大,进程正常结束,页表的映射关系解除,物理内存也可以释放。

小志的博客 2573

C++笔记-智能指针的使用及其原理

可以看出,unique_ptr并不支持拷贝,如果拷贝就会报错,并且在这里我要提一点:unique_ptr是不支持通过=号来进行初始化的,其实上面的auto_ptr也不支持,原因就是如果用=来进行初始化的,这就相当于隐式类型转换,会产生临时对象,也就会去调用拷贝构造函数,而unique_ptr是不能拷贝的,所以不支持这种初始化。而lock的作用我们上面也说了,它会返回一个管理资源的shared_ptr,相当对多了一个shared_ptr智能指针来管理资源,相应的引用计数也会增加。

2301_80236968的博客 1622

C++ 智能指针的使用及其原理

下⾯程序中我们可以看到,new了以后,我们也delete了,但是因为抛异常导,后⾯的delete没有得到执⾏,所以就内存泄漏了,所以我们需要new以后捕获异常,捕获到异常后delete内存,再把异常抛出,但是因为new本⾝也可能抛异常,连续的两个new和下⾯的Divide都可能会抛异常,让我们处理起来很⿇烦。智能指针放到这样的场景⾥⾯就让问题简单多了。

2301_79875009的博客 987

C++ —— 以真我之名 如飞花般绚丽 - 智能指针

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使⽤的内存,⼀般是忘记释放或者发⽣异常释放程序未能执⾏导致的。内存泄漏并不是指内存在物理上的消失,⽽是应⽤程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因⽽造成了内存的浪费内存泄漏的危害:普通程序运⾏⼀会就结束了出现内存泄漏问题也不⼤,进程正常结束,⻚表的映射关系解除,物理内存也可以释放。

hedhjd的博客 1万+

【探寻C++之旅】C++ 智能指针完全指南:从原理到实战,彻底告别内存泄漏

智能指针一定是你必须掌握的现代 C++ 工具。它基于 RAII 思想,自动管理动态资源,让你无需手动delete,从根源上减少内存泄漏风险。今天,我们就从 “为什么需要智能指针” 到 “不同智能指针的实战场景”,带你系统掌握这一核心特性。

2302_80243065的博客 3911

C++之智能指针

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使⽤的内存,⼀般是忘记释放或者发⽣异常释放程序未能执⾏导致的。内存泄漏并不是指内存在物理上的消失,⽽是应⽤程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因⽽造成了内存的浪费。

zzh_Zao的博客 1774

【c++】智能指针的使用及其原理

内存泄漏指因为疏忽或错误造成程序未能释放已经不再使⽤的内存,⼀般是忘记释 放或者发⽣异常释放程序未能执⾏导致的。内存泄漏并不是指内存在物理上的消失,⽽是应⽤程序分 配某段内存后,因为设计错误,失去了对该段内存的控制,因⽽造成了内存的浪费。

2401_88230254的博客 607
上一篇: 2025年8月 CentOS7.6最小安装版本 切换国内yum源(亲测有效)
下一篇: C++ 详谈智能指针(二)
万我.
博客等级 码龄1年 460粉丝 93原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值