前言
在正式介绍weak_ptr之前,我们先来回忆一下shard_ptr的一些知识,我们直到shared_ptr是采用引用计数的智能指针,多个shared_ptr实例可以指向同一个对象,并维护了一个共享的引用计数器。
深入
weak_ptr
也是一个引用计数型智能指针,但是它不增加对象的引用计数,即弱引用。与之相对,shared_ptr是强引用,只要有一个指向对象的shared_ptr存在,该对象就不会析构,直到指向对象的最后一个shared_ptr析构或reset()时才会被销毁。
利用weak_ptr,我们可以解决常见的空悬指针问题以及循环引用问题。
weak_ptr
是为了配合shared_ptr
而引入的一种智能指针,它指向一个由shared_ptr
管理的对象而不影响所指对象的生命周期,也就是将一个weak_ptr
绑定到一个shared_ptr
不会改变shared_ptr
的引用计数。
weak_ptr更像是一个助手而不是一个智能指针,它不拥有对动态对象的管辖权。
如何判断weak_ptr指向的对象是否存在?
既然weak_ptr
并不改变其所共享的shared_ptr
实例的引用计数,那就存在weak_ptr
指向的对象被释放调这种可能性,我们就不能使用weak_ptr
直接访问对象,那么我们如何判断weak_ptr
指向的对象是否存在呢?
C++提供了lock函数来实现该功能,如果对象存在,lock函数返回一个指向共享对象的shared_ptr
,否则返回一个空shared_ptr
;
如何使用weak_ptr,因为它并没有重载->和*操作符,因此不可以通过weak_ptr使用对象,典型的用法是调用其lock函数来获得shared_ptr的实例,进而访问原对象:
仿写weak_ptr
template<class _Ty>
class RefCnt
{
public:
_Ty* _Ptr; // Obj;
std::atomic_int _Uses; // shared_ptr;
std::atomic_int _Weaks; // weak_ptr;
public:
RefCnt(_Ty* p) :_Ptr(p), _Uses(1), _Weaks(1) {}
~RefCnt() {}
void _Incref() { _Uses += 1; }
void _Incwref() { _Weaks += 1; }
};
template<class _Ty> class my_weak_ptr;
template<class _Ty, class _Dx = MyDeletor<_Ty> >
class my_shared_ptr // thread;
{
private:
_Ty* _Ptr; // Object;
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(); // _Uses
}
}
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(); // _Uses;
}
return *this;
}
my_shared_ptr& operator=(my_shared_ptr&& other)
{
if (this == &other) return *this;
if (_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;//删除Refcnt
}
}
_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._ref);
}
operator bool() const { return _Ptr != nullptr; }
template<class _Ty>
friend class my_weak_ptr;
};
template<class _Ty>
class my_weak_ptr
{
private:
RefCnt<_Ty>* _Rep;
public:
my_weak_ptr() :_Rep(nullptr) {}
my_weak_ptr(const my_shared_ptr<_Ty>& other):_Rep(other._Rep)
{
if (_Rep != nullptr)
{
_Rep->_Incwref(); // Weaks;
}
}
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 (_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;
}
//弱指针不拥有资源,只是检测Ref结构是否存在
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;
}
//创建一个shared_ptr管理被引用对象
my_shared_ptr<_Ty> lock() const
{
my_shared_ptr<_Ty> _Ret;
_Ret._Ptr = _Rep->_Ptr;
_Ret._Rep = _Rep;
_Ret._Rep->_Incref();
return _Ret;
}
};