在说weak_ptr之前,需要回忆一下shared_ptr的知识。
shared_ptr是采用引用计数的智能指针,多个shared_ptr实例可以指向同一个动态对象,并维护了一个共享的引用计数器。对于引用计数发实现的计数,总是避免不了循环引用的问题。
如下实例:
class Child;
class Parent
{
public:
shared_ptr<Child> child;
Parent() {
cout << "Creat Parent" << endl; }
~Parent() {
cout << "Destory Parent" << endl; }
void hi() const{
cout << "hello" << endl; }
};
class Child
{
public:
shared_ptr<Parent> parent;
Child() {
cout << "Creat Child" << endl; }
~Child() {
cout << "Destory Child" << endl; }
};
int main()
{
shared_ptr<Parent> par(new Parent());
shared_ptr<Child> pch(new Child());
par->child = pch;
pch->parent = par;
pch->parent->hi();
return 0;
}
结果:
上面代码的运行结果很明显可以看出来没有调用Parent和Child的析构函数,这是因为Parent和Chlid的对象内部,具有各自指向对方的shared_ptr,加上par和pch这两个shared_ptr,说明每个对象的引用计数都是2。当程序退出时,即使par和pch被销毁,也仅仅是导致引用计数变为1,因此并未销毁Parent和Child。
为了解决上面这样的问题,C++11引入了weak_ptr,来打破这种循环。
1、weak_ptr
weak_ptr是为了配合shared_ptr而引入的一种智能指针,它指向一个由shared_ptr管理的对象而不影响所指对象的生命周期,也就是将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。
无论是否有weak_ptr指向,一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。
2、weak_ptr的使用
- weak_ptr的创建:
int main()
{
shared_ptr<int> sp(new int(5));
cout << "创建前sp的引用计数" << sp.use_count() << endl;
weak_ptr<int> wp(sp);
cout << "创建后sp的引用计数" << sp.use_count() << endl;
return 0;
}
结果:
- 判断weak_ptr对象是否存在
因为weak_ptr并不改变其所共享的shared_ptr实例的引用计数,那么weak_ptr所指向的对象可能已经被释放了,此时,我们就不能使用weak_ptr直接访问对象。
c++中提供了lock函数来实现该功能:如果对象存在,lock()函数返回一个指向该对象的shared_ptr,否则返回一个空的shared_ptr。
#include <iostream>
using namespace std;
class Object
{
private:
int value;
public:
Object(int x