C++智能指针之强、弱智能指针使用以及用弱智能指针解决强智能指针的循环(交叉)引用解决方法

2023-03-28 09:36:52
  • 强智能指针:资源每被强智能指针引用一次,引用计数+1,释放引用计数-1,如shared_ptr;
  • 弱智能指针:仅仅起到观察作用,观察对象释放还存在,不改变资源的引用计数,也就是说对象的引用计数是否等于0,如weak_ptr.

强智能指针的使用,带来资源的交叉引用问题:



class B;

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

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

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

    std::cout<<pa.use_count()<<std::endl;//打印对象pa的引用计数
    std::cout<<pb.use_count()<<std::endl;

    pa->ptrb = pb;
    pb->ptra = pa;

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

    return 0;
}

在这里插入图片描述
解决上述问题,引入弱智能指针:

class B;

class A{
public:
    A(){ std::cout<<"A()"<<std::endl; }
    ~A() { std::cout<<" ~A()"<<std::endl; }
    weak_ptr<B> ptrb;

    void show(){
        std::cout<<"A::show()"<<std::endl;
    }
};

class B{
public:
    B(){ std::cout<<"B()"<<std::endl; }
    ~B() { std::cout<<" ~B()"<<std::endl; }
    weak_ptr<A> ptra; //资源引用时用弱智能指针,而不是强智能指针

    void CallAshow(){
        //将ptra提升为强智能指针,调用lock(),否则无法访问A的方法,只能起观察的作用
        shared_ptr<A> p = ptra.lock();
        if(p != nullptr){
            p->show();
        }
    }
};

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

    pa->ptrb = pb;
    pb->ptra = pa;

    pb->CallAshow();
    std::cout<<pa.use_count()<<std::endl;
    std::cout<<pb.use_count()<<std::endl;
    return 0;
}

执行结果:

A()
B()
A::show()
1
1
~B()
~A()

总结:

  1. 强智能指针交叉引用会造成资源泄露问题,引入弱智能指针解决;
  2. 强智能指针引起引用计数+1,弱智能指针不会引起引用计数+1;
  3. 弱智能智能在有需要的时候可以提升为强智能指针,通过判断返回值是否为nullptr查看是否提升成功;
weak_ptr<A> ptra;
shared_ptr<A> p = ptra.lock();
if(p != nullptr){
 	//do something        
 }
  1. shared_ptr和weak_ptr都是线程安全的智能智能指针;
  2. 定义的地方或者生成资源的地方一定的是强智能指针,引用资源的地方一定使用弱智能指针。
  • 作者:KingOfMyHeart
  • 原文链接:https://blog.csdn.net/KingOfMyHeart/article/details/106988068
    更新时间:2023-03-28 09:36:52