智能指针交叉引用的注意事项

智能指针的交叉引用问题

  • shared_ptr:强智能指针 — 可以改变资源的引用计数
  • weak_ptr:弱智能指针 — 不会改变资源的引用计数(“观察者”)
#include <iostream>
#include <memory>

using namespace std;

class B; // 前置声明
class A
{
public:
    A() { cout << "A()" << endl; }
    ~A() { cout << "~A()" << endl; }
    shared_ptr<B> _ptrb;
};

class B
{
public:
    B() { cout << "B()" << endl; }
    ~B() { cout << "~B()" << endl; }
    shared_ptr<A> _ptra;
};

int main()
{
    shared_ptr<A> pa(new A());
    shared_ptr<B> pb(new B());

    pa->_ptrb = pb;
    pb->_ptra = pa;

    cout << pa.use_count() << endl;
    cout << pb.use_count() << endl;

    return 0;
}
  • 以上代码输出A() B() 2 2,显然强智能指针管理的资源未能释放,这是因为程序结束时,强智能指针管理的资源计数-1不为0,因此无法释放。(shared_ptr交叉引用会导致new的资源无法释放,进而造成资源泄露。

如何解决交叉引用造成的资源泄露问题?

注意到弱智能指针weak_ptr并不会改变资源的引用计数,相当于“观察者”,故可以采用弱智能指针来解决交叉引用问题。

#include <iostream>
#include <memory>

using namespace std;

class B;
class A
{
public:
    A() { cout << "A()" << endl; }
    ~A() { cout << "~A()" << endl; }
    weak_ptr<B> _ptrb; // 弱智能指针不会改变资源的引用计数
};

class B
{
public:
    B() { cout << "B()" << endl; }
    ~B() { cout << "~B()" << endl; }
    weak_ptr<A> _ptra; // 弱智能指针不会改变资源的引用计数
};

int main()
{
    shared_ptr<A> pa(new A());
    shared_ptr<B> pb(new B());
    
    pa->_ptrb = pb;
    pb->_ptra = pa;

    cout << pa.use_count() << endl;
    cout << pb.use_count() << endl;

    return 0;
}
  • 将强智能指针换为弱智能指针后,成功解决资源泄露问题!(即定义对象时用强智能指针;引用对象的地方使用弱智能指针

弱智能指针如何调用其它类中的方法?

实际场景中,利用弱智能指针的特性解决了资源泄露问题,但是类B想通过智能指针调用类A中的一个方法,并不能直接调用,因为弱智能指针weak_ptr只能观察资源,而无法使用资源

#include <iostream>
#include <memory>

using namespace std;

class B;
class A
{
public:
    A() { cout << "A()" << endl; }
    ~A() { cout << "~A()" << endl; }
    void testA() { cout << "testA()" << endl; }
    weak_ptr<B> _ptrb;
};

class B
{
public:
    B() { cout << "B()" << endl; }
    ~B() { cout << "~B()" << endl; }
    void func()
    {
        // _ptra->testA(); // 弱智能指针无法直接使用资源
        shared_ptr<A> ps = _ptra.lock(); // 提升方法
        if (ps != nullptr) // 提升成功!
        {
            ps->testA();
        }
    }
    weak_ptr<A> _ptra;
};

int main()
{
    shared_ptr<A> pa(new A());
    shared_ptr<B> pb(new B());

    pa->_ptrb = pb;
    pb->_ptra = pa;

    pb->func();

    cout << pa.use_count() << endl;
    cout << pb.use_count() << endl;

    return 0;
}
  • weak_ptr提升为shared_ptr以调用方法,使用_ptr.lock()进行提升,并判断是否提升成功,提升成功则可以顺利调用!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值