具有相同原始指针的 shared_ptr<Base> 和 shared_ptr<Derived> 的实例会共享引用计数吗?

Will instance of shared_ptr<Base> and shared_ptr<Derived> with same raw pointer share reference count?

假设我有两个 类、BaseDerived,其中 Derived 继承自 Base。现在,假设我执行以下代码:

shared_ptr<Derived> derivedPtr = make_shared<Derived>();
shared_ptr<Base> basePtr = derivedPtr;

derivedPtr 复制到 basePtr 是否会导致更新 derivedPtr 的引用计数(以便 derivedPtr.use_count()basePtr.use_count() 等于 2) ?或者,由于 shared_ptr 的两个实例是不同的类型,这两个实例是否具有不共享的单独引用计数(因此 derivedPtr.use_count()basePtr.use_count() 等于 1)?

所以shared_ptr不仅仅是一个指针和一个引用计数。

它是一个指针,也是一个指向控制块的指针。该控制块包含强计数、弱计数和销毁函数。

shared_ptr.

有3种构造方法

首先,您可以从原始指针构造它。当发生这种情况时,它会分配一个控制块并将一个 "destroyer" 函数插入其中以销毁原始指针内存 (delete t;)。

其次,可以使用make_shared。这为控制块和其中的对象分配了一个 space 的块。然后它将销毁器设置为只销毁对象,而不回收内存。控制块的析构函数清除了两个内存分配。

第三,别名构造函数。这些 共享 控制块(以及因此破坏代码),但具有不同的对象指针。

最常见的别名构造函数是创建指向基的指针的构造函数,您在上面就是这样做的。指向基的指针不同于您创建它的共享指针,但控制块保持不变。因此,每当控制块达到 0 强引用计数时,它就会将对象作为其原始派生对象销毁。

比较少见的可以用来return指向成员变量的共享指针,像这样:

struct Bob {
  int x;
};
auto pBob = std::make_shared<Bob>();
pBob->x = 7;
auto pInt = std::shared_ptr<int>( pBob, &(pBob->x) );

现在 pInt 是指向 pBob->x 的指针,它共享上面 2 行创建的 Bob 的引用计数(我们创建 pBob 的地方)。

pBob = {};

现在指向 Bob 的最后一个指针消失了,但对象仍然存在,由 pInt 的控制块(和强计数)所有权保持活动状态。

然后当我们:

pInt = {};

最后 Bob 被释放。

您在问题中所做的强制转换为基数的隐式转换只是其变体。

第二个别名构造函数也可以用来做非常奇怪的事情,但那是另一个话题了。


shared/weak ptr 是其中一种情况,您似乎可以 "monkey code" 它而不理解它,但根据我使用共享所有权的经验,完全理解共享 ptr 是(a ) 比获得共享所有权更容易,并且 (b) 使获得共享所有权更容易。