共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因



虽然 C++11 中的共享指针和唯一指针都允许用户定义的删除程序,但它们具有明显的语法差异,如下面的迷你示例所示:

#include "pch.h"
#include <memory>
class factory
{
public:
static factory * create() {
return new factory();
}
static void destroy(factory*    fp) noexcept{
delete fp;
}
factory(const factory &) = delete;
factory& operator= (const factory &) = delete;
private:
char * p_;
factory() {
p_ = new char[100];
}
~factory() {
delete[] p_;
}
};
int main()
{
typedef void(*fp)(factory*);
auto del = [](factory * p) noexcept {
factory::destroy(p);
};
std::shared_ptr<factory> fsptr1(factory::create(), del);
std::shared_ptr<factory> fsptr2(factory::create(), del);
//notice the syntax is different
std::unique_ptr<factory, fp> ufsptr1(factory::create(), del);
std::unique_ptr<factory, decltype(del)> ufsptr2(factory::create(), del);
return 0;
}

这背后的原因是共享指针的模板类定义为

template< class T > class shared_ptr;

并且唯一指针的模板类定义为

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

我的问题是:在这个设计决策背后有什么理由让两者的语法彼此区别吗?我天真的想法是,如果共享指针的模板类被制作为

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

这会更有意义。一方面,它与唯一指针的情况一致,另一方面,当默认删除程序格式不正确且用户无法提供自定义删除程序时,它不会实例化。

默认std::unique_ptr只存储一个元素,即指向它所保护的数据的指针。这是因为默认情况下,您希望使用尽可能少的内存量。但是,当您指定删除器时,您还需要存储它。因此,您需要区分这两个版本。

看这里: https://github.com/llvm-mirror/libcxx/blob/master/include/memory#L2397

存储是基于模板类型的特定类型。

但是对于std::shared_ptr,你没有这个约束,你已经有一个计数器,你需要分配一个块来存储它。因此,您可以在分配逻辑内部而不是外部在 API 级别做出删除选择。

看这里: https://github.com/llvm-mirror/libcxx/blob/master/include/memory#L3592

compressed_pair不在智能指针本身中,而是在分配的块中。

最新更新