删除器类型为unique_ptr与shared_ptr

Deleter type in unique_ptr vs. shared_ptr

本文关键字:ptr shared unique 类型 删除      更新时间:2023-10-16

当我发现该标准以两种完全不同的方式定义std::unique_ptrstd::shared_ptr指针可能拥有的删除器时,我觉得很奇怪。以下是来自 cppreference::unique_ptr 和 cppreference::shared_ptr 的声明:

template<
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;
template< class T > class shared_ptr;

如您所见,unique_ptr将删除器对象的类型"保存"为模板参数。这也可以从稍后从指针检索删除器的方式中看到:

// unique_ptr has a member function to retrieve the Deleter
template<
    class T,
    class Deleter = std::default_delete<T>
>
Deleter& unique_ptr<T, Deleter>::get_deleter();
// For shared_ptr this is not a member function
template<class Deleter, class T>
Deleter* get_deleter(const std::shared_ptr<T>& p);

有人能解释一下这种差异背后的合理性吗?我显然赞成这个概念unique_ptr为什么这不适用于shared_ptr?另外,为什么在后一种情况下get_deleter是非成员函数?

在这里你可以找到智能指针的原始建议:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html

它非常准确地回答了您的问题:

由于删除程序不是类型的一部分,因此更改分配策略不会破坏源或二进制兼容性,并且不需要客户端重新编译。

这也很有用,因为std::shared_ptr客户端具有更大的灵活性,例如shared_ptr具有不同删除程序的实例可以存储在同一个容器中。

此外,由于shared_ptr实现无论如何都需要一个共享内存块(用于存储引用计数),并且因为与原始指针相比,alreay 必须有一些开销,因此添加类型擦除的删除器在这里没什么大不了的。

另一方面,unique_ptr旨在完全没有开销,并且每个实例都必须嵌入其删除器,因此使其成为该类型的一部分是很自然的事情。