weak_ptr 詳解
#include <iostream>
#include <memory>
class CB;
class CA
{
public:
CA() { std::cout << "CA()" << std::endl; }
~CA() { std::cout << "~CA()" << std::endl; }
void set_ptr(std::shared_ptr<CB> &ptr) { m_ptr_b = ptr; }
private:
std::shared_ptr<CB> m_ptr_b;
};
class CB
{
public:
CB() { std::cout << "CB()" << std::endl; }
~CB() { std::cout << "~CB()" << std::endl; }
void set_ptr(std::shared_ptr<CA> &ptr) { m_ptr_a = ptr; }
private:
std::shared_ptr<CA> m_ptr_a;
};
int main()
{
std::shared_ptr<CA> ptr_a(new CA());
std::shared_ptr<CB> ptr_b(new CB());
ptr_a->set_ptr(ptr_b);
ptr_b->set_ptr(ptr_a);
std::cout << ptr_a.use_count() << " " << ptr_b.use_count() << std::endl;
return 0;
}
既然析構函數沒有調用,就說明ptr_a
和ptr_b
兩個變量的引用計數都不是0。
分析一下引用情況
#include <iostream>
#include <memory>
class CB;
class CA
{
public:
CA() { std::cout << "CA()" << std::endl; }
~CA() { std::cout << "~CA()" << std::endl; }
void set_ptr(std::shared_ptr<CB>& ptr) { m_ptr_b = ptr; }
private:
std::shared_ptr<CB> m_ptr_b;
};
class CB
{
public:
CB() { std::cout << "CB()" << std::endl; }
~CB() { std::cout << "~CB()" << std::endl; }
void set_ptr(std::shared_ptr<CA>& ptr) { m_ptr_a = ptr; }
private:
std::weak_ptr<CA> m_ptr_a;
};
int main()
{
std::shared_ptr<CA> ptr_a(new CA());
std::shared_ptr<CB> ptr_b(new CB());
ptr_a->set_ptr(ptr_b);
ptr_b->set_ptr(ptr_a);
std::cout << ptr_a.use_count() << " " << ptr_b.use_count() << std::endl;
return 0;
}
流程與上一例子大體相似,但是不同的是4這條引用是通過weak_ptr
建立的,並不會增加引用計數。也就是說,CA的對象只有一個引用計數,而CB的對象只有兩個引用計數,當main函數返回時,對象ptr_a
和ptr_b
被銷燬,也就是1,3兩條引用會被斷開,此時CA對象的引用計數會減爲0,對象被銷燬,進而解決了引用成環的問題。
參考資料