上一篇: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,至此,智能指針剖析之路可以告一段落了。