在 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/