![](/img/trans.png)
[英]Why does unique_ptr have the deleter as a type parameter while shared_ptr doesn't?
[英]Why unique_ptr doesn't prevent slicing of custom deleter?
具有custom deleter
的std::unique_ptr
的行为基于custom deleter
器的静态类型 。 没有多态性,没有基于在运行时传递的实际删除器的运行时行为,因为提供的派生删除器被切片到声明的删除器的静态类型。
(它以这种方式设计,允许使用
default deleter
的unique_ptr的大小或custom deleter without any data members
大小,以使其具有与原始指针相同的大小)。
custom deleter
的unique_ptr
静态行为: class A {};
struct BaseDeleter {
virtual void operator()(A* p) const {
std::cout << "in BaseDeleter" << std::endl;
delete p;
}
};
struct DerivedDeleter: BaseDeleter {
void operator()(A* p) const override {
std::cout << "in DerivedDeleter" << std::endl;
delete p;
}
};
int main() {
auto unique_var = std::unique_ptr<A, BaseDeleter>(new A);
unique_var = std::unique_ptr<A, DerivedDeleter>(new A);
}
输出:
in BaseDeleter
in BaseDeleter
这与std::shared_ptr
相反,后者以不同方式保存自定义删除器并允许动态行为:
shared_ptr
与custom deleter
动态行为: int main() {
auto shared_var = std::shared_ptr<A>(new A, BaseDeleter{});
shared_var = std::shared_ptr<A>(new A, DerivedDeleter{});
}
输出:
in BaseDeleter
in DerivedDeleter
代码: https : //coliru.stacked-crooked.com/a/54a8d2fc3c95d4c1
使用不同的custom deleter
分配std::unique_ptr
的行为实际上是切片 。
如果指定的unique_ptr具有不同的custom deleter
,为什么语言不会阻止std::unique_ptr
的赋值,以避免切片?
这似乎是可能的,如下所示。
unique_ptr
切割custom deleter
template<typename TYPE, typename Deleter>
struct my_unique_ptr : std::unique_ptr<TYPE, Deleter> {
using BASE = std::unique_ptr<TYPE, Deleter>;
using std::unique_ptr<TYPE, Deleter>::unique_ptr;
auto& operator=(std::nullptr_t) noexcept {
return BASE::operator=(nullptr);
}
template<typename T, typename OtherDeleter,
std::enable_if_t<!std::is_same<OtherDeleter, Deleter>::value>* dummy = nullptr>
auto& operator=(std::unique_ptr<T, OtherDeleter>&& other) = delete;
};
struct B {
virtual ~B() = default;
};
struct D : B {};
std::unique_ptr<B> b;
b = std::make_unique<D>();
这里我们有一个经典的用例。 是的,删除器被切片,但删除仍然很明确。 你的提议会干扰这一点。 并且可能很难可靠地修改为不干扰。
可以随时指定一个自定义删除器,如std::function<void(void*)>
以通过类型擦除获得多态性。 当然,它有开销,但这是选择。
默认情况下, unique_ptr
针对更常见的用例进行了优化,不常见的用例需要通过请求进行开销。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.