shared_ptr

shared_ptr是用来智能管理内存的,shared_ptr的 构造函数,拷贝构造,拷贝赋值 这三个动作都会导致 引用计数的增加,析构函数,移动拷贝,移动赋值 这三个动作都会导致 引用计数的减少。当引用计数为 0 时,指向的资源被释放,但是要记得自行把shared_ptr置空,它不会像QPointer那样进行自动置空动作。

weak_ptr

shared_ptr有一个缺陷:两个对象互相持有对方的 shared_ptr,则这两个对象无法触发自动释放。

比如:

class B;  //声明
class A
{
public:
shared_ptr<B> pb_;
~A()
{
cout << "A delete\n";
}
};

class B
{
public:
shared_ptr<A> pa_;
~B()
{
cout << "B delete\n";
}
};

void fun()
{
shared_ptr<B> pb(new B());
shared_ptr<A> pa(new A());
cout << pb.use_count() << endl; //1
cout << pa.use_count() << endl; //1
pb->pa_ = pa;
pa->pb_ = pb;
cout << pb.use_count() << endl; //2
cout << pa.use_count() << endl; //2
}

int main()
{
fun();
return 0;
}

这段代码的输出为:

1
1
2
2

可以看到 A 和 B的析构都没有被触发。如果把其中一个 shared_ptr 换为 weak_ptr 就可以了,如下:

class B;  //声明
class A
{
public:
shared_ptr<B> pb_;
~A()
{
cout << "A delete\n";
}
};

class B
{
public:
weak_ptr<A> pa_;
~B()
{
cout << "B delete\n";
}
};

void fun()
{
shared_ptr<B> pb(new B());
shared_ptr<A> pa(new A());
cout << pb.use_count() << endl; //1
cout << pa.use_count() << endl; //1
pb->pa_ = pa;
pa->pb_ = pb;
cout << pb.use_count() << endl; //2
cout << pa.use_count() << endl; //1
}

int main()
{
fun();
return 0;
}

上面这段代码输出为:

1
1
2
1 //这里之所以是1,是因为 pb->pa_ = pa; 这个语句是吧 shared_ptr赋值给weak_ptr,因此计数没增加
A delete
B delete

需要注意:weak_ptr没有实现 * 和 -> 的重载实现,因此不能直接当做指针来使用,需要先通过lock() 函数返回一个 shared_ptr ,然后再进行指针操作。