std :: shared_ptr和std :: unique_ptr构造函数之间的不对称

时间:2018-07-04 19:55:51

标签: 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

2 个答案:

答案 0 :(得分:4)

shared_ptr模板对删除程序进行类型擦除。您想要的任何一种删除器只有一个单一类型shared_ptr<T>。这是一个非常笨重(且昂贵)的工具。

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

请注意,您可以根据{em> any 删除类型shared_ptr<T>的{​​{1}}右值构造unique_ptr<T, D>


有关您的解决方案的随机评论:两种解决方案都不是很好。将函数指针用作删除器,不必要地使删除器成为unique_ptr状态的 dynamic 部分。 D情况更糟,使用整个类型擦除的虚拟调度机制进行删除-请记住,您静态知道如何删除!

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

std::function

这样,整个删除逻辑在编译时就已知,并且可以尽可能内联,而无需 additional 函数间接调用。

答案 1 :(得分:2)

您应提供删除器类型

std::unique_ptr<Y, decltype(&special_delete)> o{new Y{}, &special_delete};

请注意,将tr1::shared_ptr<X> o(new X);替换为std::unique_ptr<X> o(new X);不是一个好主意,并且一般来说也不可行。 std::unique_ptr更像是auto_ptr的替代品。