1. 简介
weak_ptr 是为配合 shared_ptrt 而引入的一种智能指针,它更像是 shared_ptr 的一个助手而不是智能指针,因为它不具备普通指针的行为,没有重载 operator * 和 ->。它的最大作用在于协助 shared_ptr 工作,像旁观者那样观测资源的使用情况。
利用 weak_ptr,我们可以解决常见的空悬指针问题和循环引用问题。
空悬指针问题:weak_ptr 不控制对象的生命期,但是它知道对象是否还活着。如果对象还存活,那么就可以将它提升为有效的 shared_ptr;如果对象已经死了(不存在),那么这种提升就会失败,返回一个空的 shared_ptr。
循环引用问题:weak_ptr 的一个重要用途是获得 this 指针的 shared_ptr,使对象自己能够生产shared_ptr 管理自己:对象使用weak_ptr 观测 this 指针,这并不影响引用计数,在需要的时候就调用lock()函数,返回一个符合要求的 shared_ptr 供外界使用。
2. weak_ptr 分析
关于weak_ptr的分析我们只进行简单的分析。下面是 weak_ptr 的源码:
template<class T> class weak_ptr
{
private:
// Borland 5.5.1 specific workarounds
typedef weak_ptr<T> this_type;
public:
typedef typename boost::detail::sp_element< T >::type element_type;
weak_ptr() BOOST_SP_NOEXCEPT : px(0), pn() // never throws in 1.30+
{
}
// generated copy constructor, assignment, destructor are fine...
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
// ... except in C++0x, move disables the implicit copy
weak_ptr( weak_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
{
}
weak_ptr & operator=( weak_ptr const & r ) BOOST_SP_NOEXCEPT
{
px = r.px;
pn = r.pn;
return *this;
}
#endif
//
// The "obvious" converting constructor implementation:
//
// template<class Y>
// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
// {
// }
//
// has a serious problem.
//
// r.px may already have been invalidated. The px(r.px)
// conversion may require access to *r.px (virtual inheritance).
//
// It is not possible to avoid spurious access violations since
// in multithreaded programs r.px may be invalidated at any point.
//
template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
#else
weak_ptr( weak_ptr<Y> const & r )
#endif
BOOST_NOEXCEPT : px(r.lock().get()), pn(r.pn)
{
boost::detail::sp_assert_convertible< Y, T >();
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible&l