1. 简介
boost.smart_ptr 库中最有价值、最重要的组成部分,也是最有用的。
shared_ptr 与 scoped_ptr 一样
包装了new 操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时才删除被包装的动态分配的对象。shared_ptr 也可以
安全地放到标准容器中,并弥补了auto_ptr 因为转移语义而不能把指针作为STL容器元素的缺陷。
2. shared_ptr 分析
通过shared_ptr 的源码我们可以看出,shared_ptr 要比同为智能指针的scoped_ptr 复杂许多。这里就列举出shared_ptr 的全部源码,我们只分析shared_ptr的重要部分。
shared_ptr 与 scoped_ptr 同样是用于管理new动态分配对象的只能指针,因此功能上有很多相似之处:它们都重载了* 和 ->操作符以模拟原始指针的行为,提供隐式bool类型转换以判断指针的有效性,get() 可以得到原始指针,并且没有提供指针算术操作。
但shared_ptr 的名字表明了它与 scoped_ptr 的主要不同:它是可以被安全共享的——shared_ptr 是一个“全功能”的类,有着正常的拷贝、赋值语义,也可以进行shared_ptr间的比较,是“最智能”的智能指针。
shared_ptr 有多钟形式的构造函数,应用于各种可能的情形:
- 无参的 shared_ptr()创建一个持有空指针的shared_ptr;
- shared_ptr(Y * p)获得指向类型T的指针p的管理权,同时引用计数置为1;
- shared_ptr(Y * p,D d)行为类似 shared_ptr(Y * p),但使用参数d指定了析构时的定制删除器,而不是简单的delete;
- shared_ptr( Y * p, D d, A a )行为类似shared_ptr(Y * p,D d),但是使用了参数a指定了构造器,被用做分配空间,允许自定义自己的构造行为;
- shared_ptr( shared_ptr const & r ) 从另外一个shared_ptr 获取指针的管理权,同时引用计数加1,结果是两个 shared_ptr 共享一个指针的管理权;
- shared_ptr( weak_ptr<Y> const & r ) 从一个weak_ptr构造shared_ptr。这使得weak_ptr的使用具有线程安全性,因为指向weak_ptr参数的共享资源的引用计数将会自增(weak_ptr不影响共享资源的引用计数)。如果weak_ptr为空(r.use_count() == 0),shared_ptr 抛出一个类型为bad_weak_ptr的异常。
- shared_ptr( std::auto_ptr<Y> & r ) 从一个auto_ptr 获得指针的管理权,同时引用计数置为1,同时auto_ptr 自动失去管理权;
- operator=赋值操作符可以从另外一个shared_ptr 或auto_ptr获取指针的管理权,其行为同构造函数。
下面是其对应的构造函数:
shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
{
}
template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
{
boost::detail::sp_pointer_construct( this, p, pn );
}
template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
{
boost::detail::sp_deleter_construct( this, p );
}
template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
{
boost::detail::sp_deleter_construct( this, p );
}
shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
{
}
template<class Y>
explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
{
boost::detail::sp_assert_convertible< Y, T >();
// it is now safe to copy r.px, as pn(r.pn) did not throw
px = r.px;
}
template<class Y>
explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
{
boost::detail::sp_assert_convertible< Y, T >();
Y * tmp = r.get();
pn = boost::detail::shared_count( r );
boost::detail::sp_deleter_construct( this, tmp );
}
shared_ptr & operator=( shared_ptr const & r ) BOOST_SP_NOEXCEPT
{
this_type(r).swap(*this);
return *this;
}
shared_ptr 的reset()函数的行为与scoped_ptr也不尽相同,它的作用是将引用计数减1,停止对指针的共享,除非引用计数为0,否则不会发生删除操作。带参数的reset()则类似相同形式的构造函数,原指针引用计数减1的同时改为管理另一个指针。
shared_ptr 有两个专门的函数来检查引用计数,unique()在shared_ptr是指针的唯一所有者时返回true(这是shared_ptr的行为类似auto_ptr或scoped_ptr),use_count()返回当前指针的引用计数。要小心,use_count()应该仅