上一篇:https://blog.csdn.net/qq_41345173/article/details/104279991
1.简介
weak_ptr是为了配合shared_ptr而引入的一种智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。值得一提的是它可以解决循环引用的问题,下面先贴一个来自http://www.cplusplus.com/reference/网站的weak_ptr的例子熟悉一下他的具体用法:
// weak_ptr::lock example
#include <iostream>
#include <memory>
int main () {
std::shared_ptr<int> sp1,sp2;
std::weak_ptr<int> wp;
// sharing group:
// --------------
sp1 = std::make_shared<int> (20); // sp1
wp = sp1; // sp1, wp
sp2 = wp.lock(); // sp1, wp, sp2
sp1.reset(); // wp, sp2
sp1 = wp.lock(); // sp1, wp, sp2
std::cout << "*sp1: " << *sp1 << '\n';
std::cout << "*sp2: " << *sp2 << '\n';
return 0;
}
Output:
*sp1: 20
*sp2: 20
2.weak_ptr源码分析
template<class T> class weak_ptr
{
private:
typedef weak_ptr<T> this_type;
template<class Y> friend class weak_ptr; //友元类的声明
template<class Y> friend class shared_ptr;
element_type * px; // contained pointer
boost::detail::weak_count pn; // reference counter
public:
typedef typename boost::detail::sp_element< T >::type element_type;
weak_ptr() BOOST_NOEXCEPT : px(0), pn() {}//无参构造
//拷贝构造
weak_ptr( weak_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn ){}
weak_ptr & operator=( weak_ptr const & r ) //重载赋值运算符
...
/*省略各种构造函数及相关赋值运算符的重载*/
shared_ptr<T> lock() const BOOST_NOEXCEPT{
return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );//若维护的shared_ptr的引用计数不为0则返回,否则为null
}
long use_count() const BOOST_NOEXCEPT{
return pn.use_count();
}
bool expired() const //看是否失效
{
return pn.use_count() == 0;
}
bool _empty() const // 判空
{
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_ptr
上面各种说明已经非常清楚,主要是weak_count类,来瞅一瞅与shared_count的区别:
class weak_count
{
private:
sp_counted_base * pi_;
观其私有成员可以看出其和shared_count必定是一样的套路,不过由于其为伴随指针,则直接接受浅拷贝即可,相对应该会简单不少,而由其源码我们也可以发现确实如此:
template<class Y>weak_ptr( shared_ptr<Y> const & r ):px( r.px ), pn( r.pn ){}
3.描绘自己的weak_ptr
#include <iostream>
#include <memory>
#include <string>
using namespace std;
template<class T> class weak_ptr;
template<class T> class shared_ptr;
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
public:
sp_counted_base(): use_count_( 1 ){}//该类唯一构造函数
virtual ~sp_counted_base(){
cout<<"sp_counted_base destroy ..."<<endl;
}
virtual void dispose() = 0;
void release() {
if(--use_count_==0)
{
dispose();
}
}
long use_count() const // nothrow
{
return static_cast<long>( use_count_ );
}
void add_ref_copy()
{
++use_count_;
}
};
template<class X> class sp_counted_impl_p: public sp_counted_base
{
private:
X * px_;
public:
explicit sp_counted_impl_p( X * px ): px_( px ){}
virtual ~sp_counted_impl_p(){
cout<<"sp_counted_impl_p destroy ..."<<endl;
}
void dispose(){
delete px_;
delete this;
}
};
class weak_count;
class shared_count
{
private:
friend class weak_count;
sp_counted_base *pi_;
public:
template <class Y>
shared_count(Y *p):pi_(new sp_counted_impl_p<Y>(p)){}
shared_count(shared_count const& r):pi_(r.pi_){
pi_->add_ref_copy();
}
explicit shared_count(weak_count const& r);
~shared_count(){
if(pi_!=0)
pi_->release();
cout<<"destroy shared_count..."<<endl;
}
long use_count(){
return pi_!=0?pi_->use_count():0;
}
};
class weak_count
{
private:
friend class shared_count;
sp_counted_base * pi_;
public:
weak_count(shared_count const &r):pi_(r.pi_){}
~weak_count(){}
weak_count(weak_count const& r):pi_(r.pi_){}
long use_count(){
return pi_!=0?pi_->use_count():0;
}
void swap(weak_count & r){
sp_counted_base *tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
};
shared_count::shared_count(weak_count const& r):pi_(r.pi_){
pi_->add_ref_copy();
}
template<class T> class shared_ptr
{
public:
T *px;
shared_count pn;
template<class Y> friend class weak_ptr; //友元类的声明
public:
shared_ptr(T *p):px(p),pn(p){}
shared_ptr(weak_ptr<T> const &r):px(r.px),pn(r.pn){}
~shared_ptr(){
cout<<"destroy shared_array..."<<endl;
}
T & operator*()const{
return *px;
}
long use_count(){
return pn.use_count();
}
};
template<class T> class weak_ptr
{
private:
template<class Y> friend class weak_ptr; //友元类的声明
template<class Y> friend class shared_ptr;
typedef weak_ptr<T> this_type;
T * px;
weak_count pn; // reference counter
public:
weak_ptr(shared_ptr<T> const &pt) :px(pt.px),pn(pt.pn){}
~weak_ptr(){
cout<<"weak_ptr destroy ..."<<endl;
}
T & operator*()const{
return *px;
}
long use_count(){
return pn.use_count();
}
shared_ptr<T> lock()const{
if(px)
return shared_ptr<T>(*this);
}
};
int main () {
shared_ptr<string> foo (new string("Hello World!"));
weak_ptr<string>bar(foo);
cout << "foo and bar\n" ;
cout<<"foo_str: "<<*foo<<"; bar_str: "<<*bar<<endl;
cout<<"foo_use_count: "<<foo.use_count()<<"; bar_use_count: "<<bar.use_count()<<endl;
shared_ptr<string>pa(bar.lock());
cout<<"foo_use_count: "<<foo.use_count()<<"; pa_use_count: "<<pa.use_count()<<endl;
return 0;
}
output:
foo and bar
foo_str: Hello World!; bar_str: Hello World!
foo_use_count: 1; bar_use_count: 1
foo_use_count: 2; pa_use_count: 2
destroy shared_array…
destroy shared_count…
weak_ptr destroy …
destroy shared_array…
sp_counted_impl_p destroy …
sp_counted_base destroy …
destroy shared_count…
显然,weak_ptr其本身并不是太复杂,代码之所以这么长是由于还包括对shared_ptr的构造,因为离开了shared_ptr的weak_ptr就没什么存在的意义了,这就是weak_ptr,至此,智能指针剖析之路可以告一段落了。