[英]How to move a unique_ptr without custom deleter to another unique_ptr with custom deleter?
#include <memory>
#include <functional>
#include <iostream>
struct TestStruct {
int a = 100;
};
struct StructDeleter {
void operator()(TestStruct *ptr) const {
delete ptr;
}
};
std::unique_ptr<TestStruct, StructDeleter> MakeNewStruct() {
std::unique_ptr<TestStruct> st(new TestStruct());
std::unique_ptr<TestStruct, StructDeleter> customDeleterSt(std::move(st));
std::cout << customDeleterSt->a << std::endl;
return customDeleterSt;
}
int main() {
auto a = MakeNewStruct();
std::cout << a->a << std::endl;
return 0;
}
上面的代码无法编译,如何将st
移动到customDeleterSt
? 我从st
创建界面获得了一个st
unique_ptr,并且我使用自定义删除器向我的用户隐藏了st
的实现,那么如何将没有自定义删除器的 unique_ptr 移动到带有自定义删除器的 unique_tr 呢?
谢谢你的帮助!
如评论中所述,蛮力方法是将源.release()
传递给目标的构造函数。 然而,有一个更优雅的解决方案(恕我直言):
添加从std::default_delete<TestStruct>
到StructDeleter
的隐式转换:
struct StructDeleter {
StructDeleter(std::default_delete<TestStruct>) {} // Add this
void operator()(TestStruct *ptr) const {
delete ptr;
}
};
现在代码可以使用现有的移动构造语法。
无论这是通过转换构造函数还是.release()
来完成,如果StructDeleter
不能(出于任何原因)正确删除std::default_delete
处理的指针,这将导致未定义的行为。 只是因为StructDeleter
调用了delete ptr
,这些技术中的任何一种都有效。
如所写, TestStruct
在delete
点不需要是一个完整的类型。 但是,如果TestStruct
获得一个重要的析构函数,您还需要确保对于任何调用StructDeleter::operator()(TestStruct*)
的代码, TestStruct
是一个完整的类型,否则您将再次回到 UB 领域。 这种保证是std::default_delete<TestStruct>
为您做的事情之一,而StructDeleter
(如所写)没有。
如果打算保持~TestStruct()
微不足道,最好添加:
static_assert(std::is_trivially_destructible<TestStruct>::value);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.