制作 shared_ptr 的副本时会发生什么?

What happens when a copy of shared_ptr is made?

我想了解当 shared_ptr 被分配给另一个时,shared_ptr 中托管对象的引用计数是如何受到影响的。

我在 C++ primer,第 5 版 中看到以下语句:

For example, the counter associated with a shared_ptr is incremented when ... we use it as the right-hand operand of an assignment... The counter is decremented when we assign a new value to the shared_ptr...

这里显示了一个例子:

auto p = make_shared<int>(42); // object to which p points has one user

auto q(p); // p and q point to the same object
           // object to which p and q point has two users

auto r = make_shared<int>(42); // int to which r points has one user
r = q; // assign to r, making it point to a different address
       // increase the use count for the object to which q points
       // reduce the use count of the object to which r had pointed
       // the object r had pointed to has no users; that object is automatically freed

当我运行一个类似的代码,以上不是我的观察:

代码:

#include<iostream>
#include<memory>

int main()
{
  std::shared_ptr<int> sh1 = std::make_shared<int>(1);
  std::shared_ptr<int> sh2 = std::make_shared<int>(2);

  sh2 = sh1;

  std::cout << "sh1 use count: " << sh1.use_count() << std::endl;
  std::cout << "sh2 use count: " << sh2.use_count() << std::endl;

  return 0;
}

Output:

sh1 use count: 2

sh2 use count: 2

sh2use_count怎么可能也是2?根据上面提到的文字,它不应该是 0 吗?我在这里遗漏了什么吗?

起初你有 sh1.use_count=1sh2.use_count=1。现在,当您使用 sh2=sh1 分配时,会发生以下情况:

  1. sh2计数器减一,因为sh2shared_ptr)要取另一个指针
  2. sh2.use_count=0以来,其指针下的对象,即int(2)被销毁。
  3. 现在您将 sh2 分配给了一个属于 sh1 的新对象,因此它的计数器增加了 1,所以:sh2.use_count=2,当然还有 sh1.use_count=2,因为两个shared_ptr对象都指向同一个对象,也就是int(1).

原来我们有

sh1.use_count =1 and 
sh2.use_count = 1
*sh1  = 1 and 
*sh2  = 2

sh2 = sh1之后。两者 sh1 ->int(1) <- sh2

int(2) 怎么了? 它被销毁,因为 sh2 现在指向 int(1)

因此,我们有

sh1.use_count == sh2.use_count
*sh1 == *sh2

*sh1 和 *sh2 有 1

我认为出现这种误解是因为您认为计数器与指向拥有对象的指针一起存储在 shared_ptr 实例中。然而实际上 shared_ptr 的实例仅包含指向内部存储对象的指针,该对象包含引用计数器和指向拥有对象的指针。因此,当您执行 sh2 = sh1; 分配时,您使 sh2 引用与 sh1 相同的内部存储对象,因此采用 sh1sh2 报告的计数器值来自同一来源。