[C++]智能指针的实现:auto_ptr, shared_ptr, weak_ptr

auto_ptr

简介

交换资源的管理权,将被拷贝资源置空,很危险,一般被禁用

代码实现

cpp 复制代码
namespace memory
{
	template<typename T>
	class auto_ptr
	{
	public:
		auto_ptr(T* ptr)
			:_ptr(ptr)
		{}

		auto_ptr(auto_ptr<T>& ap)
		{
			_ptr = ap._ptr;
			ap._ptr = nullptr;
		}
		
		~auto_ptr()
		{
			delete _ptr;
		}

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

		T& operator*()
		{
			return *_ptr;
		}
	private:
		T* _ptr;
	};
}

shared_ptr

简介

利用引用计数来控制资源的释放

代码实现

先来看一下源码中的声明

cpp 复制代码
template <class U, class D> shared_ptr (U* p, D del);
template <class D> shared_ptr (nullptr_t p, D del);

我们可能会有遇到在释放资源时,会遇到多种类型:单个、数组等,我们就需要定制适合我们的删除方式

这个del就是定制删除器

如果我们要传定制删除器,我们最好用成员来传递,也就是在构造函数中加一个参数del

cpp 复制代码
shared_ptr(T* ptr, D del)
	:_ptr = ptr
	,_pcount(new int(1))
	,_del(del)
	{}

而要用成员来传递,需要先创建这个成员

cpp 复制代码
D del;

而这个D,我们又需要在类的模板中加入这个参数,但源码中创建shared_ptr 的时候可没有这个参数,他只有一个参数

cpp 复制代码
template <class T> class shared_ptr;

那我们要怎么办呢?再封装一层吗?太麻烦了

这里我们就可以使用新学的function包装器了,因为我们确定返回值(void)和封装方式(自己传参)的

cpp 复制代码
function<void(T*)> _del;//创建的成员

//删除的时候release函数中就不是写死的了
//直接这样写即可
_del(_ptr);

还有个小问题:

对于不传删除器的调用,删除器为空,编译器报错。

我们可以直接给_del缺省值:

cpp 复制代码
[](T* _ptr){delete _ptr;}

完整代码:

cpp 复制代码
#include<functional>
using namespace std;

namespace memory
{
	template<typename T>
	class shared_ptr
	{
	public:
		templae<class D>
		shared_ptr(T* ptr, D del)
			:_ptr(ptr)
			,_pcount(new int(1))
			,_del(del)
		{}//构造

		shared_ptr(shared_ptr<T>& sp)
		{
			if (sp._ptr != _ptr)
				//防止直接或间接的给自己拷贝
			{
				_ptr = sp._ptr;
				*_pcount++;
			}
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			release();
			
			if (_ptr != sp._ptr)
			{
				_ptr = sp._ptr;
				_pcount = sp.count;
				++(*pcount);
			}
			return *this;
		}
		void release()
		{
			if (--(*_pcount) == 0)
			{
				_del(_ptr);
				delete _pcount;
			}
			else
			{
				*_pcount--;
			}
		}

		~shared_ptr()
		{
			release();
		}

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

		T& operator*()
		{
			return *_ptr;
		}
		
		int ues_count()
		{
			return *(_pcount);
		}
	private:
		T* _ptr;
		//每实例化一个对象,就产生一个指向count的指针
		int* _pcount;
		//定制删除器
		function<void(T*)>_del = [](T*) {delete _ptr; };
	};

}

weak_ptr

也是RAII,但不参与引用计数,

也就是没有_pcount,其他部分一样

结语

对于这三个指针的模拟实现到这里就结束了,

不过好像unique_ptr用的更多一些?

相关推荐
是娇娇公主~10 分钟前
Lambda表达式详解
数据结构·c++
leaves falling15 分钟前
C++ string 类:从入门到模拟实现
开发语言·c++
不早睡不改名@22 分钟前
Netty源码分析---Reactor线程模型深度解析(二)
java·网络·笔记·学习·netty
子非鱼@Itfuture34 分钟前
`<T> T execute(...)` 泛型方法 VS `TaskExecutor<T>` 泛型接口对比分析
java·开发语言
2601_9498161634 分钟前
spring.profiles.active和spring.profiles.include的使用及区别说明
java·后端·spring
样例过了就是过了36 分钟前
LeetCode热题100 柱状图中最大的矩形
数据结构·c++·算法·leetcode
wsoz44 分钟前
Leetcode哈希-day1
算法·leetcode·哈希算法
疯狂成瘾者1 小时前
接口规范设计:返回体 + 错误码 + 异常处理
java·状态模式
阿Y加油吧1 小时前
LeetCode 二叉搜索树双神题通关!有序数组转平衡 BST + 验证 BST,小白递归一把梭
java·算法·leetcode
项目帮1 小时前
Java毕设选题推荐:基于springboot区块链的电子病历数据共享平台设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
java·spring boot·课程设计