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;
}
運行結果: