shared_ptr 循环引用以及解决办法
问题代码
#include <memory>
#include <stdio.h>
using namespace std;
class A;
class B
{
public:
B() { printf("B()\n"); }
~B() { printf("~B()\n"); }
void print(){ printf("B\n"); }
shared_ptr<A> ptrA_;
};
class A
{
public:
A() {printf("A()\n"); }
~A() { printf("~A()\n"); }
shared_ptr<B> ptrB_;
};
int main()
{
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->ptrB_ = b;
b->ptrA_ = a;
printf("user count:%d %d\n", a->ptrB_.use_count(), b->ptrA_.use_count());
return 0;
}
最后打印:
./a.out
A()
B()
user count:2 2
循环引用,内存泄漏
改进版本
使用
shared_ptr<A> ptrA_ 改为 weakptr<A> ptrA_
但是类里面无法使用ptrA_, 因为weakptr只有访问权限没有控制权限
如果需要控制ptrA_, 可以这样写:
in A:
void A::func() {
shared_ptr<B> b = ptrB_.lock();
if (nullptr != b) {
b->print();
}
}
in:B
void print() { printf("a good function B\n"); }
最终代码如下
#include <memory>
#include <stdio.h>
using namespace std;
class A;
class B
{
public:
B() { printf("B()\n"); }
~B() { printf("~B()\n"); }
void print() { printf("a good function B\n"); }
weak_ptr<A> ptrA_;
};
class A
{
public:
A() {printf("A()\n"); }
~A() { printf("~A()\n"); }
void func() {
shared_ptr<B> b = ptrB_.lock();
if (nullptr != b) { //这里很重要,来判断是否能拿到制作的控制权
b->print();
}
}
weak_ptr<B> ptrB_;
};
int main()
{
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->ptrB_ = b;
b->ptrA_ = a;
a->func();
printf("user count:%d %d\n", a->ptrB_.use_count(), b->ptrA_.use_count());
return 0;
}
打印如下:(无内存泄漏)
A()
B()
a good function B
user count:1 1
~B()
~A()
总结
在类设计中,如果一个类需要引用另一个类的实例,但不希望参与其生命周期管理(即不希望增加其引用计数),则应当使用std::weak_ptr。