shared_ptr 循环引用问题以及解决办法
栗子
#include <iostream> #include <memory>class CB; class CA { public:CA() { std::cout << "CA() called! " << std::endl; }~CA() { std::cout << "~CA() called! " << std::endl; }void set_ptr(std::shared_ptr<CB> &ptr) { m_ptr_b = ptr; }void b_use_count() { std::cout << "b use count : " << m_ptr_b.use_count() << std::endl; }void show() { std::cout << "this is class CA!" << std::endl; } private:std::shared_ptr<CB> m_ptr_b; };class CB { public:CB() { std::cout << "CB() called! " << std::endl; }~CB() { std::cout << "~CB() called! " << std::endl; }void set_ptr(std::shared_ptr<CA> &ptr) { m_ptr_a = ptr; }void a_use_count() { std::cout << "a use count : " << m_ptr_a.use_count() << std::endl; }void show() { std::cout << "this is class CB!" << std::endl; } private:std::shared_ptr<CA> m_ptr_a; };void test_refer_to_each_other() {std::shared_ptr<CA> ptr_a(new CA());std::shared_ptr<CB> ptr_b(new CB());std::cout << "a use count : " << ptr_a.use_count() << std::endl;std::cout << "b use count : " << ptr_b.use_count() << std::endl;ptr_a->set_ptr(ptr_b);ptr_b->set_ptr(ptr_a);std::cout << "a use count : " << ptr_a.use_count() << std::endl;std::cout << "b use count : " << ptr_b.use_count() << std::endl; }int main() {test_refer_to_each_other();return 0; }結果
CA() called! CB() called! a use count : 1 b use count : 1 a use count : 2 b use count : 2說明
上述結果說明,該?test_refer_to_each_other 執行完成之后,并沒有釋放掉 CA 和 CB 兩個對象。因為起初定義完? ptr_a? 和 ptr_b 時,只有 ① ③ 兩條引用,然后調用函數 set_ptr 后又增加了 ② ④ 兩條引用,當 test_refer_to_each_other 這個函數返回時,對象 ptr_a 和 ptr_b 被銷毀,也就是 ① ③ 兩條引用會被斷開,但是 ② ④ 兩條引用依然存在,每一個的引用計數都不為 0,結果就導致其指向的內部對象無法析構,造成內存泄漏。
解決辦法
解決這種狀況的辦法就是將兩個類中的一個成員變量改為?weak_ptr?對象。因為 weak_ptr 不會增加引用計數,使得引用形不成環,最后就可以正常的釋放內部的對象,不會造成內存泄漏,比如將?CB?中的成員變量改為?weak_ptr?對象,代碼如下:
class CB { public:CB() { cout << "CB() called! " << endl; }~CB() { cout << "~CB() called! " << endl; }void set_ptr(shared_ptr<CA>& ptr) { m_ptr_a = ptr; }void a_use_count() { cout << "a use count : " << m_ptr_a.use_count() << endl; }void show() { cout << "this is class CB!" << endl; } private:weak_ptr<CA> m_ptr_a; };結果
CA() called! CB() called! a use count : 1 b use count : 1 a use count : 1 b use count : 2 ~CA() called! ~CB() called!通過這次結果可以看到,CA 和 CB 的對象都被正常的析構了,引用關系如下圖所示,流程與上一例子相似,但是不同的是 ④ 這條引用是通過 weak_ptr 建立的,并不會增加引用計數,也就是說 CA 的對象只有一個引用計數,而 CB 的對象只有 2 個引用計數,當 test_refer_to_each_other 這個函數返回時,對象 ptr_a 和 ptr_b 被銷毀,也就是①③兩條引用會被斷開,此時CA對象的引用計數會減為0,對象被銷毀,其內部的 m_ptr_b 成員變量也會被析構,導致 CB 對象的引用計數會減為0,對象被銷毀,進而解決了引用成環的問題。
?
(SAW:Game Over!)
總結
以上是生活随笔為你收集整理的shared_ptr 循环引用问题以及解决办法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/Cpp / STL / vector
- 下一篇: Linux / 惊群效应