c++引用计数实现的智能指针循环引用问题

文章目录

    • 引用计数实现的智能指针循环引用问题
      • 什么情况下会出现循环引用?
      • 怎么解决?
      • weak_ptr的使用策略?

引用计数实现的智能指针循环引用问题


什么情况下会出现循环引用?

简单来说,就是类A中包含了类B的智能指针对象,类B中包含了包含了类A的智能指针对象;
类A和类B的智能指针实例化SPA和SPB,当各自内部的智能指针都指向对方,这个时候就出现了循环引用。
循环引用情况下,实例SPA和SPB的引用计数为2,当各自释放的时候,引用计数减为1,并不会释放A、B的对象实例。

// CirCle.h
class ClassB;
class ClassA {
public:
    ClassA() { cout << "ClassA构造" << endl;}
    ~ClassA() { cout << "ClassA析构" << endl;}
    shared_ptr<ClassB> spb_; // ClassA中包含ClassB的智能指针对象
};

class ClassB {
public:
    ClassB() { cout << "ClassA构造" << endl;}
    ~ClassB() { cout << "ClassA析构" << endl;}
    shared_ptr<ClassA> spa_; // // ClassB中包含ClassA的智能指针对象
};

// main.cpp
shared_ptr<ClassA> spa(new ClassA()); // spa引用计数为1
shared_ptr<ClassB> spb(new ClassB()); // spb引用计数为1
spa->spb_ = spb; // spb引用计数+1为2
spb->spa_ = spa; // spa引用计数+1为2
cout << spa.use_count() << endl;  // 输出为2
cout << spb.use_count() << endl; // 输出为2
// 析构spa时,发现引用计数为2,则减少为1;析构spb时,发现引用计数为2,则减少为1;从而造成资源无法释放。


怎么解决?

在类A和类B中使用弱引用 weak_ptr 对象; weak_ptr不会增加智能指针的资源引用计数。

// CirCle2.h
class ClassB2;
class ClassA2 {
public:
    ClassA2() { cout << "ClassA构造" << endl;}
    ~ClassA2() { cout << "ClassA析构" << endl;}
    weak_ptr<ClassB2> spb_;
};

class ClassB2 {
public:
    ClassB2() { cout << "ClassA构造" << endl;}
    ~ClassB2() { cout << "ClassA析构" << endl;}
    weak_ptr<ClassA2> spa_;
};
// main.cpp
shared_ptr<ClassA2> spa(new ClassA2()); // spa引用计数为1
shared_ptr<ClassB2> spb(new ClassB2()); // spb引用计数为1
spa->spb_ = spb; // spb引用计数为1
spb->spa_ = spa; // spa引用计数为1
cout << spa.use_count() << endl;  // 输出为1
cout << spb.use_count() << endl; // 输出为1
// 析构函数正常释放spa和spb对象,从而正常释放类AB的实例

weak_ptr的使用策略?

  1. weak_ptr是c++11引入的特性,主要是为了解决shared_ptr引用循环问题。它本身是个模板类,但是不能直接生成一个实例,必须通过shared_ptr或者另一个weak_ptr来实例化,并且没有重载运算符*->,因此它不具备指针属性,它提供了lockexpired函数,通过expired可以检查对象是否有效,lock可以返回shared_ptr;当weak_ptr空悬,也称失效,则lock返回的shared_ptr为空,否则返回的shared_ptr会使引用计数增加。
  2. 利用weak_ptr有效性检查,可以将weak_ptr作为观察者,当weak_ptr失效时可以不用通知这个观察者。

你可能感兴趣的:(#,1.1,c++)