一、概述
引用《c++ primer》的话:weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。
将一个weak_ptr绑定到shared_ptr不会改变shared_ptr的引用计数【0】。一旦最后一个指向对象的shared_ptr被销毁,对象
就会被释放。即使有weak_ptr指向对象,对象也会被释放。
weak_ptr与shared_ptr继承同一个基类 _Ptr_base 因此有一样的资源指针字段、计数器字段。但是其“关注点”不一样。接下来通过源码了解一下weak_ptr构造、析构过程。
二、源码分析
1. weak_ptr构造
//[0]构造函数
template<class _Ty2,
class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
void>::type>
weak_ptr(const shared_ptr<_Ty2>& _Other) _NOEXCEPT
{ // construct weak_ptr object for resource owned by _Other
this->_Resetw(_Other);
}
//[1]调用基类构造,与shared_ptr继承同一个基类。
constexpr _Ptr_base() _NOEXCEPT
: _Ptr(0), _Rep(0)
{
// construct
}
//[2]执行构造函数体调用如下函数,实参为传入的shared_ptr对象
template<class _Ty2>
void _Resetw(const _Ptr_base<_Ty2>& _Other)
{ // release weak reference to resource and take _Other._Ptr
//[3]传入shared_ptr的引用计数器,资源指针
_Resetw(_Other._Ptr, _Other._Rep);
}
//[3]
template<class _Ty2>
void _Resetw(_Ty2 *_Other_ptr, _Ref_count_base *_Other_rep)
{ // point to _Other_ptr through _Other_rep
if (_Other_rep)
_Other_rep->_Incwref(); //[4] 递增传入shared_ptr对象的weak计数。
if (_Rep != 0)
_Rep->_Decwref();
//[5]weak对象共享shared_ptr的数据指针、计数器。
_Rep = _Other_rep;
_Ptr = const_cast<remove_cv_t<_Ty2> *>(_Other_ptr);
}
概述中【0】那句话所陈述的含义已经有解释依据即代码段中注释[4]。
weak_ptr与与之绑定的shared_ptr共享资源和计数器。
2.weak_ptr析构
~weak_ptr() _NOEXCEPT
{ // release resource
this->_Decwref();【1】
}
//[1]递减weak计数
void _Decwref()
{ // decrement weak reference count
if (_Rep != 0)
_Rep->_Decwref(); //[2]将共享的计数器中weak进行递减。
}
//[2]_Ref_count 成员,如果Weak-1为0将释放计数器
void _Decwref()
{ // decrement weak reference count
if (_MT_DECR(_Weaks) == 0)
_Delete_this(); //[3]
}
//[3]_Ref_count成员
virtual void _Delete_this() _NOEXCEPT
{
// destroy self
delete this;
}
weak_ptr析构会递减共享计数器的weaks字段。因此不会更改引用计数(uses)。
weaks字段另外一个作用就是指示weak_ptr对象是否还存在,若weak_ptr对象都没有了, 引用计数器才可以释放。