std::weak_ptr(分析、仿写)

目录

一、为什么会有weak_ptr?

1、看一个例子

2.weak_ptr 是什么?

3.weak_ ptr 如何使用?

1、如何创建weak_ ptr 实例

 2、如何判断weak_ptr指向的对象是否存在

 3、weak_ptr的使用

 二、仿写std::weak_ptr

1、c++参考手册

扫描二维码关注公众号,回复: 14622182 查看本文章

 2、代码


一、为什么会有weak_ptr?

1、看一个例子

class Child;
class Parent {
public:
	shared_ptr<Child> _child;
	~Parent() {
		cout << " Destroy Parent" << endl;
	}
	void hi()const {
		cout << "hello" << endl;
	}
};
class Child {
public:
	shared_ptr<Parent> parent;
	~Child() {
		cout << " Bey child" << endl;
	}
};
int main() {
	shared_ptr<Parent>par = make_shared<Parent>();
	shared_ptr<Child>pch = make_shared<Child>();
	par->_child = pch;
	pch->parent = par;
	pch->parent->hi();
	return 0;
}

 到最后还是没有完成析构。 

上面代码的运行结果,只打印出”Hello",而并没有打印出"Bye Parent"或"Bye Child",说明Parent和Child的析构函数并没有调用到。这是因为Parent和Child对象内部,具有各自指向对方的shared _ptr,加上parent和child这两个shared_ptr, 说明每个对象的引用计数都是2。当程序退出时,即使parent和child被销毁,也仅仅是导致引用计数变为了1,因此并未销毁Parent和Child对象。

为了解决类似这样的问题,C++11 引入了weak_ptr,来打破这种循环引用。

2.weak_ptr 是什么?

weak ptr是为了配合shared _ptr 而引入的一种智能指针,它指向一个由shared_ptr 管理的对象而不影响所指对象的生命周期,也就是将一个weak_ptr 绑定到一个shared_ptr不会改变shared_ptr 的引用计数。不论是否有weak_ptr 指向,一旦最后一个指向对象的shared_ptr 被销毁,对象就会被释放。从这个角度看,weak_ptr 更像是shared_ptr 的一个助手而不是智能指针。weak_ptr并不拥有对动态对象的管辖权,weak_ptr 指向shared_ptr 的目标也不会增加计数器的值,相反,weak_ptr 拥有一套不纳入计数器的指针系统。

3.weak_ ptr 如何使用?

接下来,我们来看看weak_ptr的简单用法。

1、如何创建weak_ ptr 实例

当我们创建一个weak_ptr 时,需要用一个shared_ptr实例来初始化weak_ptr,由于是弱共享, weak_ ptr的创建并不会影响shared_ptr 的引用计数值。
示例:

 2、如何判断weak_ptr指向的对象是否存在

既然weak_ptr并不改变其所共享的shared_ptr实例的引用计数,那就可能存在weak_ptr指向的对象被释放掉这种情况。这时,我们就不能使用weak_ptr直接的访问对象。那么如何判断weak_ptr指向的对象存在呢?

c++提供lock函数来实现该功能。

如果对象存在,lock()函数返回一个指向共享对象的shared_ptr,否则返回一个空shared_ptr。

class Object {
private:
	int value;
public:
	Object(int x = 0) :value(x) { cout << "Object Create" << endl;; }
	~Object() { cout << "Object Destroy"<<endl; }
	int GetValue()const {
		return value;
	}
};
int main() {
	shared_ptr<Object>sp(new Object(10));
	weak_ptr<Object>wp(sp);
	if (shared_ptr<Object>pa = wp.lock()) {
		cout << pa->GetValue() << endl;
	}
	else {
		cout << wp.expired() << endl;//判断对象是否被销毁
		cout << "wp 引用对象为空" << endl;
	}
	return 0;
}

 3、weak_ptr的使用

weak_ptr没有重载operator->和operator *操作符号,无法访问对象,可以使用lock()访问原始对象;

class Child;
class Parent {
public:
	weak_ptr<Child> _child;
	~Parent() {
		cout << " Destroy Parent" << endl;
	}
	void hi()const {
		cout << "hello" << endl;
	}
};
class Child {
public:
	weak_ptr<Parent> parent;
	~Child() {
		cout << " Bey child" << endl;
	}
};
int main() {
	shared_ptr<Parent>par = make_shared<Parent>();
	shared_ptr<Child>pch = make_shared<Child>();
	par->_child = pch;
	pch->parent = par;
	if (!(pch->parent.expired())) {
		pch->parent.lock()->hi();
	}
	return 0;
}

 

 二、仿写std::weak_ptr

1、c++参考手册

 2、代码

#ifndef MY_WEAK_PTR
#define MY_WEAK_PTR
#include<atomic>
template<class _Ty>
class MyDeletor
{
public:
	MyDeletor() {}
	void operator() {_Ty* ptr}const
	{
		if (ptr != nullptr)
		{
			delete ptr;
		}
	}
};
template<class _Ty>
class MyDeletor<_Ty[]>
{
public:
	MyDeletor() = default;
	void operator() { _Ty* ptr }const
	{
		if (ptr != nullptr)
		{
			delete []ptr;
		}
	}
};
template <class _Ty>
class RefCnt
{
public:
	_Ty* _Ptr;
	std::atomic_int _Uses;
	std::atomic_int _Weaks;
public:
	RefCnt(_Ty* p) :_Ptr(p), _Uses(1), _Weaks(1) {}
	~RefCnt() {}
	void _Incref() { _Uses += 1; }
	void _Incwref() { _Weaks += 1; }
};
template<class _Ty,class _Dx=MyDeletor<_Ty>>
class my_shared_ptr
{
private:
	_Ty*         _Ptr;
	RefCnt<_Ty>* _Rep;
	_Dx _mDeletor;
public:
	my_shared_ptr(_Ty* p = nullptr) :_Ptr(nullptr), _Rep(nullptr)
	{
		if (p != nullptr)
		{
			_Ptr = p;
			_Rep = new RefCnt<_Ty>(p);
		}
	}
	my_shared_ptr(const my_shared_ptr& _Y) :_Ptr(_Y._Ptr), _Rep(_Y._Rep)
	{
		if (_Rep != nullptr)
		{
			_Rep->_Incref();
		}
	}
	my_shared_ptr(my_shared_ptr&& other):_Ptr(other._Ptr),_Rep(other._Rep)
	{
		other._Ptr = nullptr;
		other._Rep = nullptr;
	}
	my_shared_ptr& operator =(const my_shared_ptr& r)
	{
		if (this == &r || this->_Ptr == r._Ptr)return *this;
		if (_Ptr != nullptr && --_Rep->_Uses == 0)
		{
			_mDeletor(_Ptr);
			if (--_Rep->_Weaks == 0)
			{
				delete _Rep;
			}
		}
		_Ptr = r._Ptr;
		_Rep = r._Rep;
		if (_Ptr != nullptr)
		{
			_Rep->_Incref();
		}
		return *this;
	}
	my_shared_ptr& operator =(my_shared_ptr&& other)
	{
		if (this == &other)return *this;
		if (this->_Ptr != nullptr && other->_Ptr != nullptr && _Ptr == other->_Ptr)
		{
			this->_Rep->_Uses -= 1;
			other->_Ptr = nullptr;
			other->_Rep = nullptr;
			return *this;
		}
		if (_Ptr != nullptr && --_Rep->_Uses == 0)
		{
			_mDeletor(_Ptr);
			if (--_Rep->_Weaks == 0)
			{
				delete _Rep;
			}
		}
		_Ptr = other._Ptr;
		_Rep = other._Rep;
		other._Ptr = nullptr;
		other._Rep = nullptr;
		return *this;
	}
	~my_shared_ptr()
	{
		if (_Rep != nullptr && --_Rep->_Uses == 0)
		{
			_mDeletor(_Ptr);
			if (--_Rep->_Weaks == 0)
			{
				delete _Rep;
			}
		}
		_Ptr = nullptr;
		_Rep = nullptr;
	}
	_Ty* get()const { return _Ptr; }
	_Ty& operator*()const { return *get(); }
	_Ty* operator ->() const { return get(); }
	size_t use_count()const
	{
		if (_Rep == nullptr)return 0;
		return _Rep->_Uses;
	}
	void swap(my_shared_ptr& r)
	{
		std::swap(_Ptr, r._Ptr);
		std::swap(_Rep, r._Rep);
	}
	operator bool()const { return _Ptr != nullptr; }
};
template <class _Ty>
class my_weak_ptr
{
private:
	RefCnt<_Ty>* _Rep;
public:
	my_weak_ptr() :_Rep(nullptr) {}
	my_weak_ptr(const my_weak_ptr<_Ty>& other) :_Rep(other._Rep)
	{
		if (_Rep != nullptr)
		{
			_Rep->_Incwref();
		}
	}
	my_weak_ptr(const my_weak_ptr& other) :_Rep(other._Rep)
	{
		if (_Rep != nullptr)
		{
			_Rep->_Incwref();
		}
	}
	my_weak_ptr(my_weak_ptr&& other) :_Rep(other._Rep)
	{
		other._Rep = nullptr;
	}
	my_weak_ptr& operator =(const my_weak_ptr& other)
	{
		if (this == &other || this->_Rep == other._Rep)return *this;
		if (this->_Rep != nullptr && --_Rep->_Weaks == 0)
		{
			delete _Rep;
		}
		_Rep = other->_Rep;
		if (_Rep != nullptr)
		{
			_Rep->_Incwref();
		}
		return *this;
	}
	my_weak_ptr& operator=(my_weak_ptr&& other)
	{
		if (this == &other)return *this;
		if (this->_Rep != nullptr && other._Rep != nullptr && _Rep == other._Rep)
		{
			this->_Rep->_Weaks -= 1;
			other._Rep = nullptr;
			return *this;
		}
		if (_Rep != nullptr && --_Rep->_Weaks == 0)
		{
			delete _Rep;
		}
		_Rep = other._Rep;
		other._Rep = nullptr;
		return *this;
	}
	my_weak_ptr& operator(const my_shared_ptr<_Ty>& other)
	{
		if (_Rep != nullptr && --_Rep->Weaks == 0)
		{
			delete _Rep;
		}
		_Rep = other->_Rep;
		if (_Rep != nullptr)
		{
			_Rep->Incwref();
		}
		return *this;
	}
	my_weak_ptr& operator =(my_shared_ptr<_Ty>&& other) = delete;
	~my_weak_ptr()
	{
		if (_Rep != nullptr && --_Rep->_Weaks == 0)
		{
			delete _Rep;
		}
		_Rep = nullptr;
	}
	bool expired()const
	{
		return this->_Rep->_Uses == 0;
	}
	my_shared_ptr<_Ty>lock()const
	{
		my_shared_ptr<_Ty>_Ret;
		_Ret._Ptr = _Rep->_Ptr;
		_Ret._Rep = _Rep;
		_Ret._Rep->_Incref;
	}
};
#endif

猜你喜欢

转载自blog.csdn.net/weixin_48560325/article/details/128052961