【问题标题】:Understanding Shared_ptr with cyclic references?用循环引用理解 Shared_ptr?
【发布时间】:2017-06-13 00:35:35
【问题描述】:

我想了解 shared_ptr 增加或减少引用计数的方式?

 #include <iostream>
 #include <memory>

class B;

class A
{
  public:
  std::shared_ptr<B> b_ptr_;
};

class B
{
  public: 
  std::shared_ptr<A> a_ptr_;
};

void func(std::shared_ptr<A> &aptr)
{
  std::shared_ptr<B> bptr = std::make_shared<B>(); //Creating shared pointer
  bptr->a_ptr_ = aptr; // Creating cyclic dependency 
  aptr->b_ptr_ = bptr;

  std::cout<<"\nFunc::a_ptr_ use_count = "<<bptr->a_ptr_.use_count();
  std::cout<<"\nFunc::b_ptr_ use_count = "<<aptr->b_ptr_.use_count();     
}

int main()
{
  std::shared_ptr<A> aptr = std::make_shared<A>();
  std::cout<<"\nBefore func::a_ptr_ use_count = "<<aptr.use_count();
  func(aptr);
  std::cout<<"\nAfter func::a_ptr_ use_count = "<<aptr.use_count();
  std::cout<<"\nAfter func::b_ptr_ use_count = "<<aptr->b_ptr_.use_count();
  return 0;   
}

Output: 
This is the output I see:
Before func::a_ptr_ use_count = 1
Func::a_ptr_ use_count = 2
Func::b_ptr_ use_count = 2
After func::a_ptr_ use_count = 2
After func::b_ptr_ use_count = 1

但是我期待这个“在 func::a_ptr_use_count = 1 之后”。在 bptr 超出 func() 的范围后,引用计数应该减少。 我在这里错过了什么?

提到的重复问题没有解释引用计数如何增加/减少。我对如何完成(在 shared_ptr 中)的内部机制更感兴趣,这在附加的其他问题的答案中没有解释。

【问题讨论】:

  • @M.M 回想起来,问题似乎是一样的
  • 好问题和+1

标签: c++ c++11 shared-ptr cyclic-reference


【解决方案1】:

为什么引用计数应该减少? bptr 可能超出范围,但 bptr 只会影响您的 B 对象的引用计数。仍然有两个对您的 A 对象的引用:

  1. 共享指针仍在main 范围内
  2. B 对象中存储的共享指针

只要有对您的A 对象的实时引用,您的B 对象就会继续存在,反之亦然(这是您通过循环共享引用有意触发的)。要使您的 B 对象消失,您需要在引用循环中将一个引用设为弱/原始,并清除存储在您的 main 方法中的指针,这样就不会保留顶级引用。

【讨论】:

  • 当func()中的bptr超出范围时,B类中a_ptr_的引用计数不应该减1吗?
  • @red_dragon:B 对象仍然存在。引用计数不是传递的;如果存在对 B 对象的 10,000 个引用,并且说 B 对象引用了 A 对象,那么 A 会从中获得一个引用。只要B 对象仍然存在,对B 对象的引用计数就会下降并不重要。由于B 对象仍然被A 对象引用,它永远不会死去(除非明确清除A 对它的引用),所以A 对象的引用计数永远不会下降。
  • 感谢您的 cmets。
  • 感谢您的 cmets。您能否在我的示例中澄清以下内容 - 一旦 func() 中的 bptr 超出范围,bptr 的引用计数将单独减少,但 a_ptr 的引用计数仍然为 2,因为 bptr 的内存仍然存在并且它仍然引用 aptr .确实,如果一个对象的内存没有被释放,那么即使该对象变量超出范围,对该对象内共享指针的所有引用仍然保留。
  • 是的。只要存在指向对象的单个共享指针,该对象就存在,并且它不会破坏自己的共享指针(或任何其他资源)。您的问题是考虑对象超出范围。它没有。它从未在范围内。共享指针bptr 在作用域内,当它超出作用域时它被销毁,但在此之前创建了另一个指向同一对象的共享指针,因此对象本身保持活动状态。
猜你喜欢
  • 2012-09-02
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-16
  • 1970-01-01
  • 2011-10-19
相关资源
最近更新 更多