现在的位置: 首页 > 综合 > 正文

weak_ptr解除循环引用

2013年10月10日 ⁄ 综合 ⁄ 共 1047字 ⁄ 字号 评论关闭

先看一下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()

问题解决。

抱歉!评论已关闭.