智能指针:共享型shared_ptr的底层逻辑

基础三大组件

1. 自定义删除器 + 数组特化

  • 普通删除器:operator()delete ptr
  • 数组特化版本:operator()delete[] ptr
  • 作用:统一普通对象 / 数组的释放方式,解耦销毁逻辑

2. 引用计数块(计数器类 my_rescount

成员:

  • 资源指针:_Ty* _mptr 保存托管对象地址
  • 强引用:atomic<int> uses 记录 shared_ptr 个数
  • 弱引用:atomic<int> weaks 记录 weak_ptr 关联数

必须实现的接口:

  1. 构造函数:初始化资源指针、uses=1weaks=1
  2. 强引用自增:increase_s() 拷贝 shared_ptr 调用
  3. 弱引用自增:increase_w() 拷贝 weak_ptr 调用
  4. 获取强计数:uses_count() 返回 uses.load ()
  5. 获取弱计数:weak_count() 返回 weaks.load ()
  6. 强引用自减:reduce_s()``--uses 到 0 → 销毁托管资源 + 调用弱引用减 1
  7. 弱引用自减:reduce_w()``--weaks 到 0 → 销毁计数块自身

3. 核心智能指针类 my_shared_ptr

内部三个成员:

  • _Ty* _mptr:指向托管的真实资源
  • my_rescount<_Ty>* _count指向堆上唯一的计数块
  • _Dx _deleter:删除器对象

必须实现的成员函数:

  1. 构造相关

  2. 普通构造:my_shared_ptr(_Ty* p)有资源就 new 一个计数块_count 指向

  3. 析构函数:调用 reset() 自动计数减一、释放资源

  4. 拷贝 / 移动语义

  5. 拷贝构造 :共享资源和计数块 → uses++

  6. 拷贝赋值:先释放旧资源,再共享新资源、计数 ++

  7. 移动构造:抢夺对方资源和计数,对方置空

  8. 移动赋值:清空自身、抢夺对方资源,对方置空

  9. 核心功能接口

  10. reset():放弃当前资源,计数减一,为 0 则释放资源

  11. reset(指针):放弃旧资源,接管新资源、新建计数块

  12. get():返回原生裸指针

  13. swap():交换两个 shared_ptr 的资源和计数块

  14. 运算符重载

  15. operator*:解引用

  16. operator->:成员访问

  17. operator bool:判空(是否托管有效资源)

cpp 复制代码
//测试类
class Int
{
private:
	int value;
public:
	Int() :value(0) { cout << "Int()\n" << value << endl; }
	Int(int x) :value(x) { cout << "Int(int x)\n" << value << endl; }
	~Int() { cout << "~Int()" << endl; }
	Int(const Int &other) :value(other.value) { cout << "copy Int(Int other)\n" << value << endl; }
	Int& operator=(const Int& other)
	{
		if (this != &other)
		{
			value = 0;
			value = other.value;
		}
		cout << "move" << endl;
		return *this;
	}
};

//删除器
template<class _Ty>
struct my_delete
{
	void operator()(_Ty* p)const
	{
		delete p;
	}
};

//特化删除器
template<class _Ty>
struct my_delete<_Ty[]>
{
	void operator()(_Ty* p)const
	{
		delete[]p;
	}
};

//计数器
template<class _Ty>
class my_rescount
{
	//公共接口
public:
	using element_type = _Ty;
	using pointer = _Ty*;
	//类成员
private:
	//指针
	pointer _mptr;
	//uses计数器,原子类型
	std::atomic<int>uses;
	//weaks计数器
	std::atomic<int>weaks;
	//普通接口函数
public:
	//构造函数
	my_rescount(pointer o_mptr) :
		_mptr(o_mptr), uses(0), weaks(0)
	{
		if (_mptr != nullptr)
		{
			uses = 1;
			weaks = 1;
		}
	}
	//析构函数
	~my_rescount()= default;
	//拷贝一次shared_ptr计数加1
	void increase_s()
	{
		++uses;
	}
	//拷贝一次weak_ptr计数加1
	void increase_w()
	{
		++weaks;
	}
	//返回值
	int uses_count()const
	{
		return uses.load();
	}
	int weak_count()const
	{
		return weaks.load();
	}
	//删一次shared_ptr减减,减为零时调用reduce_w,返回
	int reduce_s()
	{
		if (--uses==0)
		{
			reduce_w();
		}
		return uses.load();
	}
	//删一次Weak_ptr减减,减为零时返回
	int reduce_w()
	{
		if (--weaks != 0) {

		}
		return weaks.load();
	}
};

//普通模版
template<class _Ty,class _Dx=my_delete<_Ty>>
class my_shared_ptr
{
	//公共接口
public:
	using pointer = _Ty*;
	using element_type = _Ty;
	using my_deleter = _Dx;
	using my_count = my_rescount<_Ty>*;
	//成员
private:
	pointer _mptr;
	my_count _count;
	my_deleter _deleter;
	//公共接口函数
public:
	//删除当前智能指针,首先指向计数器的指针不为空,其次uses数量为0,也要判断weak的数量,数量为0,一起删
	void reset()
	{
		if (_count != nullptr && _count->reduce_s() == 0)
		{
			_deleter(_mptr);
			if (_count->reduce_w() == 0)
			{
				delete _count;
			}
			_mptr = nullptr;
			_count = nullptr;
		}
	}
	//删除当前指针,并且赋予新的指针,新的指针要有新的计数器,要重新申请
	void reset(pointer p)
	{
		reset();
		_mptr = p;
		//有了新指针,就会有新的计数器继续计数
		if (_mptr != nullptr)
		{
			_count = new my_rescount<_Ty>(_mptr);
		}
	}
	//看一眼智能指针
	pointer get()const
	{
		return get();
	}
	//获取删除器
	my_deleter get_delete()const
	{
		return _deleter;
	}
	//交换函数
	void swap(my_shared_ptr& other)
	{
		std::swap(other._mptr, this->_mptr);
		std::swap(other._count, this->_count);
	}
	//运算符重载
	_Ty& operator*()
	{
		return *get();
	}
	pointer operator->()
	{
		return get();
	}
	operator bool()
	{
		return get() != nullptr;
	}
public:
	//构造函数
	my_shared_ptr(pointer p=nullptr) :_mptr(p), _count(nullptr)
	{
		if (_mptr != nullptr)
		{
			//在堆上创建了一个计数器并且让_count指向计数器,new表达式返回的就是新对象的地址
			_count = new my_rescount<_Ty>(_mptr);
		}
	}
	//析构函数
	~my_shared_ptr()
	{
		reset();
	}
	//拷贝构造
	my_shared_ptr(const my_shared_ptr& other) :_mptr(other._mptr), _count(other._count)
	{
		if (_mptr != nullptr)
		{
			_count->increase_s();
		}
	}
	//移动构造
	my_shared_ptr(my_shared_ptr&& other) :_mptr(other._mptr), _count(other._count)
	{
		other._mptr = nullptr;
		other._count = nullptr;
	}
	//赋值
	my_shared_ptr& operator=(const my_shared_ptr& other)
	{
		my_shared_ptr(other).swap(*this);
		return *this;
	}
	//移动赋值
	my_shared_ptr& operator=(my_shared_ptr&& other)
	{
		my_shared_ptr(std::move(other)).swap(*this);
		cout << "std::move" << endl;
		return *this;
	}
};

//普通模版
template<class _Ty, class _Dx>
class my_shared_ptr<_Ty[],_Dx>
{
	//公共接口
public:
	using pointer = _Ty*;
	using element_type = _Ty;
	using my_deleter = _Dx;
	using my_count = my_rescount<_Ty>*;
	//成员
private:
	pointer _mptr;
	my_count _count;
	my_deleter _deleter;
	//公共接口函数
public:
	//删除当前智能指针,首先指向计数器的指针不为空,其次uses数量为0,也要判断weak的数量,数量为0,一起删
	void reset()
	{
		if (_count != nullptr && _count->reduce_s() == 0)
		{
			_deleter(_mptr);
			if (_count->reduce_w() == 0)
			{
				delete _count;
			}
			_mptr = nullptr;
			_count = nullptr;
		}
	}
	//删除当前指针,并且赋予新的指针,新的指针要有新的计数器,要重新申请
	void reset(pointer p)
	{
		reset();
		_mptr = p;
		//有了新指针,就会有新的计数器继续计数
		if (_mptr != nullptr)
		{
			_count = new my_rescount<_Ty>(_mptr);
		}
	}
	//看一眼智能指针
	pointer get()const
	{
		return get();
	}
	//获取删除器
	my_deleter get_delete()const
	{
		return _deleter;
	}
	//交换函数
	void swap(my_shared_ptr& other)
	{
		std::swap(other._mptr, this->_mptr);
		std::swap(other._count, this->_count);
	}
	//运算符重载
	_Ty& operator[](int index)
	{
		return get()[index];
	}
	operator bool()
	{
		return get() != nullptr;
	}
public:
	//构造函数
	my_shared_ptr(pointer p = nullptr) :_mptr(p), _count(nullptr)
	{
		if (_mptr != nullptr)
		{
			//在堆上创建了一个计数器并且让_count指向计数器,new表达式返回的就是新对象的地址
			_count = new my_rescount<_Ty>(_mptr);
		}
	}
	//析构函数
	~my_shared_ptr()
	{
		reset();
	}
	//拷贝构造
	my_shared_ptr(const my_shared_ptr& other) :_mptr(other._mptr), _count(other._count)
	{
		if (_mptr != nullptr)
		{
			_count->increase_s();
		}
	}
	//移动构造
	my_shared_ptr(my_shared_ptr&& other) :_mptr(other._mptr), _count(other._count)
	{
		other._mptr = nullptr;
		other._count = nullptr;
	}
	//赋值
	my_shared_ptr& operator=(const my_shared_ptr& other)
	{
		my_shared_ptr(other).swap(*this);
		return *this;
	}
	//移动赋值
	my_shared_ptr& operator=(my_shared_ptr&& other)
	{
		my_shared_ptr(std::move(other)).swap(*this);
		cout << "std::move" << endl;
		return *this;
	}
};

void funa()
{
	my_shared_ptr<Int>pa(new Int(10));
	my_shared_ptr<Int>pb;
	pb = std::move(new Int(12));
	my_shared_ptr<Int>pc;
	pc = pb;
}

void funb()
{
	my_shared_ptr<Int[]>pa(new Int[10]);
	printf("\n");
	my_shared_ptr<Int[]>pb;
	pb = std::move(new Int[12]);
	my_shared_ptr<Int[]>pc;
	pc = pb;
}

int main()
{
	funa();
	funb();
}
相关推荐
不负岁月无痕11 小时前
STL-- C++ vector类 模拟实现
开发语言·c++
丘山望岳12 小时前
C++模板特化:类型与常量的灵活掌控
c语言·开发语言·c++
晚风叙码12 小时前
从0吃透C++入门|第一个程序、命名空间与缺省函数基础
开发语言·c++
j_xxx404_12 小时前
Linux线程:核心机制与优雅的 C++ 封装实践|附源码
linux·运维·服务器·开发语言·c++·人工智能·ai
W230357657312 小时前
手写 muduo 库:基于 Reactor 模型打造高性能网络通信框架
c++·reactor·tcp·muduo库
Zhang~Ling12 小时前
C++ 模板进阶:非类型参数、特化与分离编译深度解析
开发语言·c++
Oj92q85H512 小时前
如何在Dev-C++中使用TDM-GCC编译项目
linux·开发语言·c++
小poop12 小时前
STL 入门 + 三道高频面试题
c++
j_xxx404_12 小时前
Linux线程控制:从用户态控制到内核级克隆全链路解析
linux·运维·服务器·开发语言·c++·ai