weak_ptr

一、weak_ptr的诞生

1.为什么会有weak_ptr,看下面例子

class b;
class a 
{
public:
	shared_ptr<b> _b;
	~a() {
		cout << "destroy a" << endl;
	}
	void hi()const
	{  
		cout << "hi" << endl;
	}
};
class b 
{
public:
	shared_ptr<a> _a;
	~b()
	{
		cout << "destory b" << endl;
	}
};
int main()
{
	shared_ptr<a>pa = make_shared<a>();
	shared_ptr<b>pb = make_shared<b>();
	pa->_b = pb;
	pb->_a = pa;
	pb->_a->hi();
	return 0;
}

 上述代码的运行结果,只打印出“hi”,说明a和b的析构函数并没有调用到。这是因为a和b的对象内部,具有各自指向对方的shared_ptr,并且a和b的引用计数都是2.当程序退出时,引用计数减为1,对象并没有被析构掉。可以简单理解如下图:

运行结果如下

 

二、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的目标也不会增加计数器值。

1.创建weak_ptr

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

int main()
{
	shared_ptr<int>a1(new int(5));
	cout << a1.use_count() << endl;
	weak_ptr<int>a2(a1);
	cout << a1.use_count() << endl;
	return 0;
    
}

运行结果如下

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

既然weak_ptr并不改变其所共享的shared_ptr实例的引用计数,那就可能存在weak_ptr指向对象被释放掉这种情况。这时,我们就不能使用weak_ptr直接的访问对象,C++通过lock()函数实现该功能。

如果对象存在,loick()函数返回一个指向共享对象的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>pa(new Object(10));
	weak_ptr<Object>pb(pa);
	if (shared_ptr<Object>pc = pb.lock())
	{
		cout << pc->GetValue() << endl;
	}
	else
	{
		cout << pb.expired() << endl;
		cout << "pb 引用对象为空" << endl;
	}
	return 0;
}

 3.weak_ptr的使用

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

class b;
class a
{
public:
	weak_ptr<b> _b;
	~a() {
		cout << "destroy a" << endl;
	}
	void hi()const
	{
		cout << "hi" << endl;
	}
};
class b
{
public:
	weak_ptr<a> _a;
	~b()
	{
		cout << "destory b" << endl;
	}
};
int main()
{
	shared_ptr<a>pa = make_shared<a>();
	shared_ptr<b>pb = make_shared<b>();
	pa->_b = pb;
	pb->_a = pa;
	if (!(pb->_a.expired()))
	{
		pb->_a.lock()->hi();
	}
	return 0;
}

运行结果

 三、仿写weak_ptr

#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;
	}
};

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值