先看一下shared_ptr的正確用法:
class A {public: A() { cout << "A::A()" << endl; } ~A() { cout << "A::~A()" << endl; } shared_ptr<B> b;};class B {public: B() { cout << "B::B()" << endl; } ~B() { cout << "B::~B()" << endl; } public: shared_ptr<A> a;};/* * */int main(int argc, char** argv) { shared_ptr<A> x(new A);
此時運行程式,顯示:
A::A()A::~A()
好,A對象被正確的建立和銷毀了。
但是注意A對象裡面有一個shared_ptr指向B.
現在修改一下代碼,讓它出現循環參考。
int main(int argc, char** argv) { shared_ptr<A> x(new A); x->b = shared_ptr<B>(new B); x->b->a = x; return 0;}
再運行程式,觀察結果:
A::A()B::B()
A和B對象都未釋放。為什嗎?
因為第一行x指向的A對象,A對象的引用計數為1,
第二行 x->b指向B對象,B對象的引用計數為1
第三行B對象裡面的a也指向了A對象,因此A對象的引用計數為2
當退出main函數的時候,
1.x的解構函式會將A對象的引用計數從2減到1,但是因為不是0,所以A對象的解構函式不會被調用。
2.因此A裡面成員變數b的解構函式就不會被調用。
3.所以B的引用計數也是1.
4.所以出現了兩個記憶體流失,A和B對象都沒有被銷毀。
為了打破這個循環參考,試試weak_ptr。只需要修改一行代碼即可,將B的成員a改成wear_ptr<A>類型。下面是完整代碼:
class B;class A {public: A() { cout << "A::A()" << endl; } ~A() { cout << "A::~A()" << endl; } shared_ptr<B> b;};class B {public: B() { cout << "B::B()" << endl; } ~B() { cout << "B::~B()" << endl; } public: weak_ptr<A> a;};/* * */int main(int argc, char** argv) { shared_ptr<A> x(new A); x->b = shared_ptr<B>(new B); x->b->a = x; return 0;}
運行結果:
A::A()B::B()A::~A()B::~B()
問題解決。