先看一下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对象被正确的创建和销毁了。
但是注意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()
问题解决。