先看一下shared_ptr的正确用法:
class A {
public:
A() {
cout << "A::A()" << endl;
}
~A() {
cout << "A::~A()" << endl;
}
shared_ptr<B> b;
};
class B {
public:
B() {
cout << "B::B()" << endl;
}
~B() {
cout << "B::~B()" << endl;
}
public:
shared_ptr<A> a;
};
/*
*
*/
int main(int argc, char** argv) {
shared_ptr<A> x(new A);
此时运行程序,显示:
A::A()
A::~A()
但是注意A对象里面有一个shared_ptr指向B.
现在修改一下代码,让它出现循环引用。
int main(int argc, char** argv) {
shared_ptr<A> x(new A);
x->b = shared_ptr<B>(new B);
x->b->a = x;
return 0;
}
再运行程序,观察结果:
A::A()
B::B()
A和B对象都未释放。为什么?
因为第一行x指向的A对象,A对象的引用计数为1,
第二行 x->b指向B对象,B对象的引用计数为1
第三行B对象里面的a也指向了A对象,因此A对象的引用计数为2
当退出main函数的时候,
1.x的析构函数会将A对象的引用计数从2减到1,但是因为不是0,所以A对象的析构函数不会被调用。
2.因此A里面成员变量b的析构函数就不会被调用。
3.所以B的引用计数也是1.
4.所以出现了两个内存泄漏,A和B对象都没有被销毁。
为了打破这个循环引用,试试weak_ptr。只需要修改一行代码即可,将B的成员a改成wear_ptr<A>类型。下面是完整代码:
class B;
class A {
public:
A() {
cout << "A::A()" << endl;
}
~A() {
cout << "A::~A()" << endl;
}
shared_ptr<B> b;
};
class B {
public:
B() {
cout << "B::B()" << endl;
}
~B() {
cout << "B::~B()" << endl;
}
public:
weak_ptr<A> a;
};
/*
*
*/
int main(int argc, char** argv) {
shared_ptr<A> x(new A);
x->b = shared_ptr<B>(new B);
x->b->a = x;
return 0;
}
运行结果:
A::A()
B::B()
A::~A()
B::~B()
问题解决。