了解 C++ std::shared_ptr

Understanding C++ std::shared_ptr

我有一个问题,请看下面这个简单的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 对象中的一个变量。

As far as i know reference count is a variable in each shared_ptr object.

不,引用计数存储在堆上的一个"control block"中。每个 shared_ptr 实例都指向同一个 "control block" 并保持它的活动状态(直到所有实例和所有与它们共享所有权的 weak_ptr 实例都死了)。

一个shared_ptr<T>通常实现为两个指针。一个指向对象数据,一个指向如下所示的结构:

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

其中 [object ptr] 指向实际对象。

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

顺便说一句,当您调用 make_shared 时,它会:

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

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

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

摘自@Estinox 的答案——这不是答案,这里是关于共享 ptr 如何工作的Channel9 talk