關於shared_ptr與weak_ptr的使用

shared_ptr是帶引用計數的智能指針,可以說大部分的情形選擇用shared_ptr不會出問題。那麼weak_ptr是什麼,應該怎麼用呢?
weak_ptr也是智能指針,但是比較弱,感覺沒什麼用。其實它的出現是伴隨shared_ptr而來,尤其是解決了一個引用計數導致的問題:在存在循環引用的時候會出現內存泄漏。
關於循環引用,看下面這個小例子就足夠了:

#include <iostream>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;

class BB;
class AA
{
public:
    AA() { cout << "AA::AA() called" << endl; }
    ~AA() { cout << "AA::~AA() called" << endl; }
    shared_ptr<BB> m_bb_ptr;  //!
};

class BB
{
public:
    BB() { cout << "BB::BB() called" << endl; }
    ~BB() { cout << "BB::~BB() called" << endl; }
    shared_ptr<AA> m_aa_ptr; //!
};

int main()
{
    shared_ptr<AA> ptr_a (new AA);
    shared_ptr<BB> ptr_b ( new BB);
    cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
    cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
    //下面兩句導致了AA與BB的循環引用,結果就是AA和BB對象都不會析構
    ptr_a->m_bb_ptr = ptr_b;
    ptr_b->m_aa_ptr = ptr_a;
    cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
    cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
}

運行結果:
這裏寫圖片描述
可以看到由於AA和BB內部的shared_ptr各自保存了對方的一次引用,所以導致了ptr_a和ptr_b銷燬的時候都認爲內部保存的指針計數沒有變成0,所以AA和BB的析構函數不會被調用。解決方法就是把一個shared_ptr替換成weak_ptr。

#include <iostream>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;

class BB;
class AA
{
public:
    AA() { cout << "AA::AA() called" << endl; }
    ~AA() { cout << "AA::~AA() called" << endl; }
    weak_ptr<BB> m_bb_ptr;  //!
};

class BB
{
public:
    BB() { cout << "BB::BB() called" << endl; }
    ~BB() { cout << "BB::~BB() called" << endl; }
    shared_ptr<AA> m_aa_ptr; //!
};

int main()
{
    shared_ptr<AA> ptr_a (new AA);
    shared_ptr<BB> ptr_b ( new BB);
    cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
    cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
    //下面兩句導致了AA與BB的循環引用,結果就是AA和BB對象都不會析構
    ptr_a->m_bb_ptr = ptr_b;
    ptr_b->m_aa_ptr = ptr_a;
    cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
    cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
}

運行結果:
這裏寫圖片描述

關於weak_ptr更詳細的說明可以閱讀boost的文檔,絕對的寶庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章