shared_ptr如何<void>知道要使用哪个析构函数?

How does shared_ptr<void> know which destructor to use?

本文关键字:析构函数 gt ptr 如何 lt shared void      更新时间:2023-10-16

我编写了以下代码来查看当shared_ptr<void>shared_ptr<Thing>的最后一个引用并且本身被销毁时的行为。

#include <iostream>
#include <string>
#include <memory>
using namespace std;
struct Thing{
~Thing(){
cout<<"Destroyedn";
}
int data;
};
int main(){
{
shared_ptr<void> voidPtr;
{
shared_ptr<Thing> thingPtr = make_shared<Thing>();
voidPtr = thingPtr;
}
cout<<"thingPtr is deadn";
}
cout<<"voidPtr is deadn";
return 0;
}

哪些输出:

thingPtr is dead
Destroyed
voidPtr is dead

它的行为方式是我喜欢的,但它完全出乎意料,我想了解这里发生了什么。 最初的共享指针不再存在,它最终只是一个shared_ptr<void>。 所以我希望这个共享指针的行为就像它拿着一个void*并且不知道Thing::~Thing(),但它调用它。 这是设计使然,对吧? 空共享指针是如何实现这一点的?

共享指针共同拥有的共享状态还包含一个删除器,这是一个类似于对象的函数,在其生存期结束时馈送托管对象以释放它。我们甚至可以使用适当的构造函数指定我们自己的删除器。删除程序的存储方式以及它所经历的任何类型的擦除都是实现细节。但只要说共享状态包含一个函数就足够了,该函数确切地知道如何释放拥有的资源。

现在,当我们使用make_shared<Thing>()创建具体类型的对象并且不提供删除器时,共享状态设置为保存一些可以释放Thing的默认删除器。该实现可以仅从模板参数生成一个。由于它存储为共享状态的一部分,因此它不依赖于可能共享状态所有权的任何shared_pointer<T>的类型T。它将永远知道如何释放Thing

因此,即使我们将voidPtr作为唯一剩下的指针,删除器也保持不变,并且仍然知道如何释放Thing。当voidPtr超出范围时,这就是它的作用。

shared_ptr只知道如何处理具有已知接口的管理对象。该管理对象提供两个引用计数(自身较弱,托管对象为强),并包含删除器(仅在类型已知时提供调用之外的访问权限)和要删除的指针(私有)。

shared_ptr指向什么类型和对象与它使用的管理对象完全分开,尽管为了理智起见,它不应该更长。