简述环状引用问题及其解决方案

两个shared_ptr指针所指向对象的数据成员中,如果含有指向对方对象的share_ptr指针则会产生环状引用。通过例子来解释:

class A{

public:

      shared_ptr<B> bptr;

      ~A(){cout<<"~A()"<<endl;}

};

class B{

public:

      shared_ptr<A> aptr;

      ~B(){cout<<"~B()"<<endl;}

};

int main(){

      shared_ptr<A> a(new A());

      shared_ptr<B> b(nwe B());

      a->bptr=b;

      b->aptr=a;

}

 

  • 程序中通过new创建了一个类A的对象和一个类B的对象并通过shared_ptr指向它们,之后通过指向另一个对象的智能指针对自身的数据成员ptr进行赋值,因此两个对象的引用计数都为2.
  • 当程序退出时,main函数中创建的智能指针由于生命周期结束,其所指向对象的引用计数减1,但是由于环状引用,对象内部的智能指针的生命周期都不会结束,两个对象的引用计数始终为1.
  • 具体来讲,就是对象A中的智能指针bptr只有在对象A析构之后才会结束其生命周期,从而将对象B的引用计数降为0;二对象A并不会被销毁,因为对象A销毁的条件是指向A的智能指针的引用计数降为0,而对象B指向A的智能指针只有在B对象析构后才会结束其生命周期,从而将对象A的引用计数降为0.
  • 因此上述逻辑就成了一个死结,就好像两个人大家都就揪着对方的头发,并且叫嚣着只要对方松手自己就松手,但是两个人谁也不愿意首先让步,结果这两个人始终保持着同样的姿势,除非某一方实在坚持不住放弃了。
  • 程序中不存在某个对象坚持不住首先主动释放的情况,因此必须处理环状引用的问题。解决环状引用问题的钥匙就是weak_ptr,因为weak_ptr不会增加对象的引用计数。

class A{

public:

      weak_ptr<B> bptr;

      ~A(){cout<<"~A()"<<endl;}

};

class B{

public:

      weak_ptr<A> aptr;

      ~B(){cout<<"~B()"<<endl;}

};

int main(){

      shared_ptr<A> a(new A());

      shared_ptr<B> b(nwe B());

      a->bptr=b;

      b->aptr=a;

}

  • 将类中的智能指针类型有shared_ptr改为weak_ptr,在main函数中初始化两个智能指针时会将对象的引用计数加1,但是对类中的数据成员进行赋值时不会增加对象的引用计数。程序退出时,main函数中创建的两个智能指针生命周期结束,对象的引用计数由1减为0,对象空间释放。
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值