weak_ptr
本身也是一个模板类,但是不能直接用它来定义一个智能指针的对象,只能配合shared_ptr
来使用,可以将shared_ptr的对象赋值给weak_ptr
,并且这样并不会改变引用计数的值。查看weak_ptr的代码时发现,它主要有lock
、swap
、reset
、expired
、operator=
、use_count
几个函数,与shared_ptr相比多了lock
、expired
函数,但是却少了get
函数,甚至连operator*
和 operator->
都没有
weak_ptr解决循环引用
weak_ptr
必须跟shared_ptr
配合使用, 它用于解决shared_ptr
的死锁问题,如果两个shared_ptr
一直互相引用,那么它们的引用计数永远不是0,资源永远不释放,这样实际造成了内存泄露。weak_ptr
并不拥有其指向的对象,让weak_ptr
指向shared_ptr
所指向对象,对象的引用计数并不会增加
循环引用的情况:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Son;
class Father
{
public:
~Father() {cout<<" father 析构"<<endl; }
shared_ptr<Son> son_;
};
class Son {
public:
~Son() {cout<<" son 析构"<<endl; }
shared_ptr<Father> father_;
};
auto father = make_shared<Father>();
auto son = make_shared<Son>();
father->son_ = son;
son->father_ = father;
结果一个析构函数也没运行,说明对象资源没有释放。使用weak_ptr
解决很简单,让Son的成员变量father改为weak_ptr
类型,运行后发现两个析构都有了。
main函数退出前,Son对象的引用计数是2,而Father的引用计数是1。
son指针销毁,Son对象的引用计数变成1。
father指针销毁,Father对象的引用计数变成0,导致Father对象析构,Father对象的析构会导致它包含的son_指针被销毁,这时Son对象的引用计数变成0,所以Son对象也会被析构。