C++ | shared_ptr与weak_ptr

文章目录

  • 前言
  • 一、shared_ptr与weak_ptr是什么?
    • 1.shared_ptr的内存模型
    • 2.weak_ptr的内存模型
  • 二、仿写系统的shared_ptr与weak_ptr
    • 1.mdeletor
    • 2.Ref_con
    • 3.shared_ptr
    • 4.weak_ptr
  • 三、解决循环引用问题
  • 四、总结


前言

简单介绍shared_ptr与weak_ptr,仿写系统的shared_ptr与weak_ptr,并解决循环引用的问题.


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

一、shared_ptr与weak_ptr是什么?

shared_ptr是一种智能指针(smart pointer),作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。这便是所谓的引用计数(reference counting)。一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。
weak_ptr是为配合shared_ptr而引入的一种智能指针。

1.shared_ptr的内存模型

C++ | shared_ptr与weak_ptr_第1张图片

2.weak_ptr的内存模型

C++ | shared_ptr与weak_ptr_第2张图片

二、仿写系统的shared_ptr与weak_ptr

1.mdeletor


```cpp
class Mdeletor
{
public:
	Mdeletor() = default;
	void operator()(_Ty* p)const
	{
		if (p != NULL)
		{
			delete p;
		}
		p = NULL;
	}
};

template
class Mdeletor<_Ty[]>
{
public:
	Mdeletor() = default;
	void operator()(_Ty* p)const
	{
		if (p != NULL)
		{
			delete[]p;
		}
		p = NULL;
	}
};

2.Ref_con

template<typename _Ty>
class RefCnt
{
protected:
	_Ty* ptr;
	std::atomic_int Uses;
	std::atomic_int Weaks;
public:
	RefCnt(_Ty* p) :ptr(p), Uses(1), Weaks(1) {}
	~RefCnt() {}
	void IncUses()
	{
		Uses += 1;
	}
	void IncWeaks()
	{
		Weaks += 1;
	}
	template<typename _Ty, typename _Dx>
	friend class my_shared_ptr;

	template<typename _Ty>
	friend class my_weak_ptr;
};

3.shared_ptr

代码如下(示例):

template<typename _Ty,typename _Dx= Mdeletor<_Ty>>
class my_shared_ptr
{
private:
	_Ty* Ptr;
	RefCnt<_Ty>* Ref;
	_Dx mdeletor;
public:
	my_shared_ptr(_Ty* p = nullptr) :Ptr(nullptr),Ref(nullptr)
	{
		if (p != nullptr)
		{
			Ptr = p;
			Ref = new RefCnt<_Ty>(p);
		}
	}
	my_shared_ptr(const my_shared_ptr& other):Ptr(other.Ptr),Ref(other.Ref)//拷贝构造
	{
		if (Ptr != NULL)
		{
			Ref->IncUses();
		}
	}
	my_shared_ptr(my_shared_ptr&& other) :Ptr(other.Ptr), Ref(other.Ref)//移动构造
	{
		other.Ptr = NULL;
		other.Ref = NULL;
	}

	my_shared_ptr& operator=(const my_shared_ptr& other)//赋值
	{
		if (this == &other || Ptr == other.Ptr)  return *this;//自赋值,直接返回本身
		
		if (Ptr != NULL && --Ref->Uses == 0)//被赋值的智能指针对象拥有资源,
		{                                   //且该对象仅被该智能指针拥有
			mdeletor(Ptr);//释放该对象
			if (--Ref->Weaks == 0)//当弱引用计数为零时
			{
				delete Ref;//析构引用计数对象
				Ref = NULL;
			}
		}

		Ptr = other.Ptr;
		Ref = other.Ref;
		if (Ptr != NULL)
		{
			Ref->IncUses();
		}
		return *this;
	}

	my_shared_ptr& operator=(my_shared_ptr&& other)//移动赋值
	{
		if (this == &other)  return *this;
		if (Ptr == other.Ptr && Ptr != NULL)//当两个智能指针使用同一个对象时,且该对象不为空
		{
			other.Ptr = NULL;//去掉other的使用权
			other.Ref = NULL;
			Ref->Uses -= 1;//强引用计数-1

			return *this;
		}

		if (Ptr != NULL && --Ref->Uses == 0)
		{
			mdeletor(Ptr);
			if (--Ref->Weaks == 0)
			{
				delete Ref;
				Ref = NULL;
			}
		}
		Ptr = other.Ptr;
		Ref = other.Ref;

		other.Ptr = NULL;
		other.Ref = NULL;

		return *this;
	}

	~my_shared_ptr()
	{
		if (Ptr != NULL && --Ref->Uses == 0)
		{
			mdeletor(Ptr);
			if (--Ref->Weaks == 0)
			{
				delete Ref;
			}
		}
		Ref = NULL;
	}

	_Ty* get()const
	{
		return Ptr;
	}

	_Ty& operator*()
	{
		return *get();
	}

	_Ty* operator->()
	{
		return get();
	}

	size_t use_count()const
	{
		if (Ref == NULL)  return 0;
		return Ref->Uses;
	}

	void swap(my_shared_ptr& other)
	{
		std::swap(Ptr, other.Ptr);
		std::swap(Ref, other.Ref);
	}

	operator bool()const
	{
		return Ptr != NULL;
	}
	template<typename _Ty>
	friend class my_weak_ptr;
};

4.weak_ptr

代码如下(示例):

template<typename _Ty>
class my_weak_ptr
{
private:
	RefCnt<_Ty>* wRef;
public:
	my_weak_ptr() :wRef(NULL) {}
	my_weak_ptr(const my_shared_ptr<_Ty>& other) :wRef(other.Ref)//共享指针构造
	{
		if (wRef!=NULL)
		{
			wRef->IncWeaks();
		}
	}

	my_weak_ptr(const my_weak_ptr& other) :wRef(other.wRef)//拷贝构造
	{
		if (wRef != NULL)
		{
			wRef->IncWeaks();
		}
	}

	my_weak_ptr(my_weak_ptr&& other) :wRef(other.wRef)//移动构造
	{
		other.wRef = NULL;
	}

	my_weak_ptr& operator=(const my_weak_ptr& other)
	{
		if (this == &other||wRef=other.wRef)  return *this;//自赋值或者是两个指针指向同一个对象

		if (this != NULL && --wRef->Weaks == 0)//是否自己独占对象
		{
			delete wRef;
		}

		wRef = other.wRef;
		if (wRef != NULL)
		{
			wRef->IncUses();
		}

		return *this;
	}
	my_weak_ptr& operator=(my_weak_ptr&& other)
	{
		//1 判断是否自赋值
		if (this == &other)  return *this;

		//2 判断是否是指向同一个对象的两个指针相互赋值
		if (wRef == other.wRef && wRef != NULL)//如果是
		{
			other.wRef = NULL;
			wRef->Weaks -= 1;
			return *this;
		}

		//3 两个指向不同对象的指针赋值
		if (this != NULL && --wRef->Weaks == 0)//是否自己独占对象
		{
			delete wRef;//如果独有
		}

		wRef = other.wRef;
		other.wRef = NULL;
		
		return *this;
	}
	my_weak_ptr& operator=(const my_shared_ptr<_Ty>& other)//共享智能指针给弱指针赋值
	{
		if (wRef == other.Ref)  return *this;

		if (wRef != NULL && --wRef->Uses == 0)
		{
			delete wRef;
		}
		wRef = other.Ref;

		if (wRef != NULL)
		{
			wRef->IncWeaks();
		}

		return *this;
	}
	my_weak_ptr& operator=( my_shared_ptr<_Ty>&& other) = delete;
	~my_weak_ptr()
	{
		if (wRef != NULL && --wRef->Weaks == 0)
		{
			delete wRef;
			
		}
		wRef = NULL;
	}
	bool expired()const//判断被引用的对象是否删除,若删除则返回真
	{
		return wRef->Uses == 0;
	}
	my_shared_ptr<_Ty> lock()const
	{
		my_shared_ptr<_Ty>tmp;
		tmp.Ptr = wRef->ptr;
		tmp.Ref = wRef;
		tmp.Ref->IncUses();
		return tmp;

	}
};

该处使用的url网络请求的数据。


三、解决循环引用问题

C++ | shared_ptr与weak_ptr_第3张图片

四、总结

weak_ptr一般需要与shared_ptr联合使用,且若要使用weak_ptr时需要用lock()函数返回一个shared_ptr的对象再进行使用。

你可能感兴趣的:(C++,c++)