weak_ptr是用来解决shared_ptr的循环引用问题的。先看看如何构造weak_ptr:
int main(int argc, char** argv) {
shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);
weak_ptr<int> x;
weak_ptr<int> y(new int(6));
最后一个创建语句编译报错,因为weak_ptr构造函数不能像普通智能指针一样接受裸指针。
看看构造函数的几种实现:
weak_ptr(): px(0), pn() // never throws in 1.30+
{
}
这是默认构造函数,两个成员变量分别是:
T * px; // contained pointer
boost::detail::weak_count pn; // reference counter
px是裸指针,默认构造函数将之置为0pn是引用计数器,这是一个对象。但是这个计数器对象用的却不是shared_ptr里面采用的类型。如果从shared_ptr获得的指针交给了weak_ptr, weak_ptr内部使用的是不同的引用计数器,也就是打破了引用循环。
weak_count以后再分析,大概功能先了解到这里。
现在看一个重要函数lock
shared_ptr<T> lock() const // never throws
{
return shared_ptr<element_type>( *this, boost::detail::sp_nothrow_tag() );
}
weak_ptr的lock函数内部用自己构造了一个shared_ptr对象,然后返回之。看一下shared_ptr的构造函数,只要weak_ptr参数的引用计数不为空, 就将其中的指针赋给自己。lock因为传递了sp_nothrow_tag给shared_ptr构造函数, 因此不会抛出异常。如果不想这样,也可以直接shared_ptr构造函数。
因此将weak_ptr变为shared_ptr有两种方法,
1.用lock
2.用shared_ptr构造函数
template<class Y>
weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
: px(r.lock().get()), pn(r.pn) // never throws
{
}
这个构造函数接受weak_ptr作为参数。lock参考下面的解释。这里要注意,weak_ptr不提供get方法获取裸指针,只能通过lock().get()获取。也就是先转成shared_ptr,再获取裸指针。
template<class Y>
weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
: px( r.px ), pn( r.pn ) // never throws
{
}
这个构造函数接受shared_ptr作为参数。