【问题标题】:Understanding C++ std::shared_ptr理解 C++ std::shared_ptr
【发布时间】:2018-10-22 09:35:08
【问题描述】:

我有一个问题,请通过以下简单的C++程序,

int main( )
{
 shared_ptr<int> sptr1( new int );
 shared_ptr<int> sptr2 = sptr1;
 shared_ptr<int> sptr3;
 shared_ptr<int> sptr4;
 sptr3 = sptr2;

 cout<<sptr1.use_count()<<endl;
 cout<<sptr2.use_count()<<endl;
 cout<<sptr3.use_count()<<endl;

 sptr4 = sptr2;

 cout<<sptr1.use_count()<<endl;
 cout<<sptr2.use_count()<<endl;
 cout<<sptr3.use_count()<<endl;

 return 0;
}

输出:

3
3
3
4
4
4

sptr1sptr3 对象如何知道引用计数在打印 4 时增加。

据我所知,引用计数是每个 shared_ptr 对象中的一个变量。

【问题讨论】:

  • Vittorio 的答案是完美的,但值得退一步问自己:您描述的引用计数是否真的计算引用的数量?如果没有,它有什么用,为什么有人会编写具有该功能的智能指针?
  • “据我所知,引用计数是每个 shared_ptr 对象中的一个变量。” 这怎么可能起作用?如果每个对象都不知道您何时复制 其他 对象,那么引用计数将毫无意义。
  • 这个问题没有特定的版本 - 甚至没有特定的标准,关于 boost 中的shared_ptr 的相同问题将有完全相同的答案。这是一个关于拥有引用计数所有权的智能指针的一般问题
  • @JonathanWakely 公平地说,他们意识到了这一点,因此提出了问题
  • 一个更好的问题可能是:为什么所有三个引用计数都相同?一旦你回答了这个问题,你的问题就会自行回答

标签: c++ shared-ptr smart-pointers reference-counting


【解决方案1】:

据我所知,引用计数是每个 shared_ptr 对象中的一个变量。

不,引用计数存储在堆上的“控制块”中。每个shared_ptr 实例都指向同一个“控制块”并使其保持活动状态(直到所有实例和与其共享所有权的所有weak_ptr 实例都死了)。

【讨论】:

  • 直到所有实例以及与其共享所有权的所有weak_ptr实例都死了
【解决方案2】:

shared_ptr&lt;T&gt; 通常实现为两个指针。一个用于对象数据,一个用于结构,如下所示:

[strong reference count]
[weak reference count]
[type-erased destroyer fptr]
[type-erased destroyer data]

[object ptr] 指向实际对象。

当您复制shared_ptr 时,它会创建另一个指向上述数据(以及实际对象)的指针,并递增其中的[strong reference count] 部分。弱指针的行为类似,但增加了[weak reference count](当 strong 为 0 且 weak 为非零时,类型擦除的销毁器被调用,但控制块仍然存在)。

顺便说一句,当您拨打 make_shared 时,它会:

[strong reference count]
[weak reference count]
[type-erased destroyer fptr]
[object data]

现在指向对象的指针指向控制块末尾的[object data]。这会将分配的数量减少到一个。

需要一个单独的数据和控制块指针,因为诸如派生的shared_ptr可以更改为base的shared_ptr等特性;在许多情况下,这需要调整指针值。同样,shared ptr 的别名构造函数允许控制块和指向的对象完全不相关。

取自 @Estinox 的 answer-that-isn't-an-answer,这里是 Channel9 talk 分享 ptr 的工作原理。

【讨论】:

  • "上述数据的另一个副本"不清楚;什么“高于数据”?
  • @curiousguy 改写
猜你喜欢
  • 2011-09-27
  • 2014-01-11
  • 1970-01-01
  • 2011-10-29
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多