c++ - std::shared_ptr 和 std::unique_ptr 构造函数之间的不对称性

标签 c++

在 C++03 期间,我们没有 unique_ptr,所以我使用了 tr1::shared_ptr

现在,在 C++11 中,在这种情况下,我正在替换这样的调用:

tr1::shared_ptr<X> o(new X); 

std::unique_ptr<X> o(new X);

不幸的是,出于某种原因,我无法替换包含删除器的案例,其中删除器是一个函数:

void special_delete(Y *p) { ... }

tr1::shared_ptr<Y> o(new Y(), special_delete); 


std::unique_ptr<Y> o(new Y(), special_delete);  // does not compile
std::unique_ptr<Y, std::function<void(Y*)> > o(new Y(), special_delete);  // this compiles

为什么会这样? 有没有一种方法可以用 unique_ptr 构造函数替换所有 shared_ptr 构造函数?

我创建了这个,但我对此并不十分满意..

template <class Y>
using unique_ptr_with_deleter = std::unique_ptr<Y, std::function<void(Y*)> >;

unique_ptr_with_deleter<Y> o(new Y(), special_delete);  // this compiles

最佳答案

shared_ptr模板类型删除删除器。只有一种类型 shared_ptr<T>对于您想要的任何类型的删除器。这是一个非常重量级(且昂贵)的工具。

相比之下,unique_ptr使删除器成为类型的一部分,因此它没有动态调用开销。 unique_ptr<T, D>几乎和原始指针一样便宜。

请注意,您可以构造一个 shared_ptr<T>来自unique_ptr<T, D> 任何删除器类型的右值D .


对您的解决方案的随机评论:两种解决方案都不是很好。使用函数指针作为删除器不必要地使删除器成为 unique_ptr 状态的动态部分。 std::function情况更糟,使用整个类型删除虚拟分派(dispatch)机制进行删除——请记住,您静态知道如何删除!

更好的解决方案是通过编写您自己的类型,使删除器成为类型的一部分,而不是值的一部分:

struct YDeleter { void operator()(Y* p) { special_delete(p); } };

std::unique_ptr<Y, YDeleter> p(new Y);   // or presumaby some special factory

那样的话,整个删除逻辑在编译时是已知的,并且可以尽可能内联,而不需要额外的函数调用间接。

关于c++ - std::shared_ptr 和 std::unique_ptr 构造函数之间的不对称性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51180121/

相关文章:

c++ - C++十进制类型和括号-为什么?

c++ - X11/Xlib : Create "GlassPane"-Window

c++ - 来自 Voronoi 的 Delaunay boost : missing triangle with non-integral point coordinates

c++ - 如何解析质数的倍数 C++?

c++ - 集合和字典( map )的一个类

c++ - 如何向 QFileSystemModel 添加自定义角色

c++ - 使用 BOOST::associative property map 插入 boost::BIMAP ... 失败

C++无法同时使用枚举和开关

c++ - 以结构为键的 std::map

c++ - 固定宽度字体 - Symbian C++ CEikLabel