C++ 使用deallocator&;共享ptr中的分配器

C++ 使用deallocator&;共享ptr中的分配器,c++,shared-ptr,smart-pointers,C++,Shared Ptr,Smart Pointers,我使用的库函数很少返回使用malloc或new创建的指针。 因此,我有自己的客户deallocator,它基于所使用的分配类型 例如 shared_ptr ptr1(LibFunctA(),&MallocDeleter)//LibFunctA返回使用malloc创建的指针 共享的ptr ptr2(LibFunctB(),&newDeleter)//LibFunctB返回使用新 现在,我知道这是上面提到的deallocator的一个非常幼稚的用法,但是它还大量用于其他什么场景呢 此外,如何使用客

我使用的库函数很少返回使用malloc或new创建的指针。 因此,我有自己的客户deallocator,它基于所使用的分配类型

例如

shared_ptr ptr1(LibFunctA(),&MallocDeleter)//LibFunctA返回使用malloc创建的指针
共享的ptr ptr2(LibFunctB(),&newDeleter)//LibFunctB返回使用新
现在,我知道这是上面提到的deallocator的一个非常幼稚的用法,但是它还大量用于其他什么场景呢

此外,如何使用客户分配器?我试图分配一个自定义分配器,如下所示,但现在我实际上如何调用它?这种功能在哪里有帮助

shared_ptr<int> ptr3(nullptr_t, &CustomDeleter, &CustomAllocator);  //assume both functs are defined somewhere.
shared_ptr ptr3(nullptr_t,&CustomDeleter,&CustomAllocator)//假设两个函数都定义在某个地方。
我看不出以这种方式使用删除器有任何“幼稚”之处。这毕竟是该功能的主要目的;销毁未使用标准C++方法分配的指针对象。


分配器用于您需要控制如何分配和删除
共享的\u ptr
的内存控制块时。例如,您可能有一个内存池,您希望这些东西来自该内存池,或者如果您处于内存有限的情况下,通过
new
分配内存是不可接受的。由于控制块的类型取决于
shared\u ptr
,因此除了使用某种分配器之外,没有其他方法可以控制它的分配方式。

用于
shared\u ptr
的自定义删除程序对于包装一些(通常)C资源非常有用,您需要在这些资源上调用释放函数。例如,您可以执行以下操作:

shared_ptr<void> file(::CreateFileW(...), ::CloseHandle);
shared_ptr文件(::CreateFileW(…),::CloseHandle);

类似的例子在C库中比比皆是。这样可以避免以后手动释放资源并处理可能的异常和其他问题。

我认为自定义分配器将用于为“共享计数”对象分配空间,该对象存储deallocator(deleter)和引用计数器的副本

至于自定义删除器可以用于什么

前面已经提到了一个用途:使
共享\u ptr
与某些特殊功能必须删除的对象兼容(例如
文件
,该文件由
fclose
删除),而不必将其包装到负责正确删除的帮助器类中

自定义删除器的另一个用途是池。池可以分发使用“特殊”删除器初始化的
共享\u ptr
,该删除器不会真正删除任何内容,而是将对象返回到池中

还有一件事:deleter已经是实现一些
shared\u ptr
特性所必需的。例如,被删除的类型在创建时总是固定的,并且与正在初始化的
共享的类型无关

Vou可以创建一个
共享\u ptr
,方法是使用
派生的
对其进行初始化
shared_ptr
保证删除对象时,即使
Base
没有虚拟dtor,也会将其作为
派生的
删除。为了实现这一点,
shared_ptr
已经存储了一些关于如何删除对象的信息。因此,允许用户指定一个完全自定义的deleter不需要任何成本(在运行时性能方面),也不需要太多额外的代码


可能还有几十种其他的场景可以很好地使用自定义删除器,这正是我到目前为止所想到的。

这里有。可能相关:。在上面的例子中,我如何让ptr3指向新分配的块?我找不到任何方法来调用CustomAllocator函数。有没有分配器的工作示例?@FrankQ:为什么它会调用自定义分配器?你给了它一个空指针;没有人叫它储存任何东西。因为它没有存储任何东西,所以也没有使用分配器分配任何东西。它也不会用deleter删除任何内容。
shared_ptr<void> file(::CreateFileW(...), ::CloseHandle);