weak_ptr源码分析
来源:互联网 发布:中国海外间谍知乎 编辑:程序博客网 时间:2024/04/29 15:18
之前分析了shared_ptr的框架,这次来说一下shared_ptr的兄弟weak_ptr,它们常常是一起出现的。
weak_ptr顾名思义就是弱指针,它不会增加对象的引用计数,欸有重载operator*和operator->,使用时,应当通过weak_ptr的lock函数构造一个shared_ptr。
作用:防止循环引用(以后博客分析)。应用:在enable_shared_from_this类中,它有一个weak_ptr weak_this_成员。当对象构造完成后,在类成员函数内部可以调用shared_from_this获得该对象自身类型的shared_ptr。千万不要在构造函数里调用share_from_this,因为this还没有完全构造出来,此时无法根据this构造一个正确的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; //pn是weak_count,而不是shared_count,所以weak_ptr不会引起指针引用计数增加。 weak_ptr() BOOST_NOEXCEPT : px(0), pn() // never throws in 1.30+ { }// generated copy constructor, assignment, destructor are fine...//如果 定义"BOOST没有右值引用" 为假#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )// ... except in C++0x, move disables the implicit copy //支持copy assignment weak_ptr( weak_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) { } weak_ptr & operator=( weak_ptr const & r ) BOOST_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 >(); } template<class Y> weak_ptr( weak_ptr<Y> && r ) BOOST_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) //强转为右值 { boost::detail::sp_assert_convertible< Y, T >(); r.px = 0; } // for better efficiency in the T == Y case weak_ptr( weak_ptr && r ) BOOST_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) { r.px = 0; } // for better efficiency in the T == Y case weak_ptr & operator=( weak_ptr && r ) BOOST_NOEXCEPT { this_type( static_cast< weak_ptr && >( r ) ).swap( *this ); return *this; } template<class Y> weak_ptr( shared_ptr<Y> const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) //重点weak_ptr的pn=shared_ptr的pn,也就是说weak_count=shared_count { boost::detail::sp_assert_convertible< Y, T >(); }#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) template<class Y> weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_NOEXCEPT { boost::detail::sp_assert_convertible< Y, T >(); px = r.lock().get(); pn = r.pn; return *this; }#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template<class Y> weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_NOEXCEPT { this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this ); return *this; }#endif template<class Y> weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_NOEXCEPT { boost::detail::sp_assert_convertible< Y, T >(); px = r.px; pn = r.pn; return *this; }#endif //将weak_ptr提升为shared_ptr,如果已经过期,则返回一个空shared_ptr shared_ptr<T> lock() const BOOST_NOEXCEPT { return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() ); //调用shared_ptr(const weak_ptr<T>& r, sp_nothrow_tag()); } //返回shared_ptr的引用计数,pn是weak_count类型,但是它实际上转调它持有的sp_counted_base指针(和shared_ptr持有同一个)的use_count()函数,所以可以返回所有shared_ptr引用计数的相关信息,下同。 long use_count() const BOOST_NOEXCEPT { return pn.use_count(); } //判断shared_ptr是否过期,也就是引用计数是否为0,如果为0,说明shared_ptr已经过期死了,返回true bool expired() const BOOST_NOEXCEPT { return pn.use_count() == 0; } bool _empty() const // extension, not in std::weak_ptr { return pn.empty(); } void reset() BOOST_NOEXCEPT // never throws in 1.30+ { this_type().swap(*this); } void swap(this_type & other) BOOST_NOEXCEPT { std::swap(px, other.px); pn.swap(other.pn); } template<typename Y> void _internal_aliasing_assign(weak_ptr<Y> const & r, element_type * px2) { px = px2; pn = r.pn; } template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT { return pn < rhs.pn; } template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT { return pn < rhs.pn; }
下面是weak_count的源码:
class weak_count{private: sp_counted_base * pi_; friend class shared_count;public: weak_count(): pi_(0) // nothrow { } weak_count(shared_count const & r): pi_(r.pi_) // nothrow { if(pi_ != 0) pi_->weak_add_ref(); } weak_count(weak_count const & r): pi_(r.pi_) // nothrow { if(pi_ != 0) pi_->weak_add_ref(); }// Move support#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) weak_count(weak_count && r): pi_(r.pi_) // nothrow { r.pi_ = 0; }#endif ~weak_count() // nothrow { if(pi_ != 0) pi_->weak_release(); //weak_count析构一次,就减少一次sp_count_base的计数!!!!!! } weak_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; if( tmp != pi_ ) { if(tmp != 0) tmp->weak_add_ref(); if(pi_ != 0) pi_->weak_release(); pi_ = tmp; } return *this; } weak_count & operator= (weak_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; if( tmp != pi_ ) { if(tmp != 0) tmp->weak_add_ref(); if(pi_ != 0) pi_->weak_release(); pi_ = tmp; } return *this; } void swap(weak_count & r) // nothrow { sp_counted_base * tmp = r.pi_; r.pi_ = pi_; pi_ = tmp; } long use_count() const // nothrow { return pi_ != 0? pi_->use_count(): 0; } bool empty() const // nothrow { return pi_ == 0; } friend inline bool operator==(weak_count const & a, weak_count const & b) { return a.pi_ == b.pi_; } friend inline bool operator<(weak_count const & a, weak_count const & b) { return std::less<sp_counted_base *>()(a.pi_, b.pi_); }};//在这里初始化shared_count中的那两个函数,即利用wakt_count的sp_count_base初始化share_count的sp_count_base,它们是共享的//这是在调用weak_ptr的lock函数用weak_ptr构造shared_ptr,然后调用本函数的inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ){ if( pi_ == 0 || !pi_->add_ref_lock() ) { boost::throw_exception( boost::bad_weak_ptr() ); }}inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ ){ if( pi_ != 0 && !pi_->add_ref_lock() ) { pi_ = 0; }}
值得注意的是,weak_ptr自身也是引用计数型智能指针,也有引用计数。weak_ptr也支持拷贝分配之类的函数。
上面代码最后的这两个函数是shared_count类的构造函数之一,这是使用weak_ptr的lock函数底层要调用的之一。lock函数是使用weak_ptr构造shared_ptr,这回调用shared_ptr的weak_ptr构造方法,然后shared_ptr的成员shread_count自然也要调用以weak_ptr为参数的构造方法。并且由于lock提升这个操作有多线程并发的可能,所以这里调用的不是sp_counted_base函数的add_ref_copy(该函数是原子的,但功能简单,不能说明提升成功或失败),而是add_ref_lock函数,gcc版本是这样实现的:
inline int atomic_conditional_increment( int * pw ){ spinlock_pool<1>::scoped_lock lock( pw ); int rv = *pw; if( rv != 0 ) ++*pw; return rv;}
首先对pw的内存进行上锁,然后再进行相应操作。如果*pw不为0,则weak_ptr提升成功,增加引用计数。如果为0,说明shared_ptr对象已死,不能提升,不增加引用计数,返回0。在shared_count构造函数中(就是上面那个),取消pi_的赋值(不打算指向weak_ptr的sp_counted_base),将它重新赋为空。
如此一来,便可实现weak_ptr提升称为shared_ptr的线程安全了。
- weak_ptr源码分析
- C++ 智能指针(shared_ptr/weak_ptr)源码分析
- shared_ptr,weak_ptr源码解析
- Boost源码学习---weak_ptr.hpp
- 详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- weak_ptr
- weak_ptr
- weak_ptr
- weak_ptr
- weak_ptr
- weak_ptr
- 从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- [置顶] 从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- 从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- boost智能指针之shared_ptr,scoped_ptr,intrusive_ptr,weak_ptr源码简析
- 3.weak_ptr
- boost::weak_ptr
- c++ weak_ptr
- 树的最长链
- 关于压缩jar包时提示*.*没有这个文件或目录的问题以及解决办法:
- 如何在 Linux 中启用 Shell 脚本的调试模式
- 数据结构的学习之路(三)--树
- Singleton
- weak_ptr源码分析
- CodeForces 456C - Boredom(DP)
- linux关于网络的命令介绍
- HDU 5934 Bomb(强连通缩点)
- CentOS安装MySQL与登录退出
- 运维请注意:”非常危险“的Linux命令大全
- HDU 5938 - Four Operation(贪心)
- Book 【GDKOI2017模拟1.21】
- c++之面向对象