带自定义删除器的std::unique_ptr如何通过std::make_unique调用类构造函数?
问题分析与解决方案
首先得明确:std::make_unique天生不支持直接搭配自定义删除器使用,这就是你报错的根源。
为什么会报错?
你写的std::make_unique<A, Deleter>(5),编译器会把模板参数里的Deleter理解为「A的构造函数需要接收的参数类型」,而不是unique_ptr的删除器类型。所以它期望你传入一个Deleter对象,但你传了int类型的5,自然就触发了类型转换错误。
标准库的make_unique设计初衷是简化使用默认删除器的unique_ptr创建流程,它的模板参数只用来指定要创建的对象类型,以及构造函数的参数类型,根本没有预留指定自定义删除器的位置。
正确的实现方式
方式一:手动构造unique_ptr
直接跳过make_unique,用unique_ptr的构造函数来创建,同时传入动态分配的对象和自定义删除器实例:
#include <memory> struct Deleter { void operator() (A* a) {} }; class A { A(int a) {} friend int main(); // 必须让main能访问私有构造函数,否则new A(5)会报错 }; int main() { std::unique_ptr<A, Deleter> unique(new A(5), Deleter()); }
方式二:封装自己的「带删除器的make_unique」
如果你习惯用类似make_unique的简洁语法,可以自己封装一个模板函数:
#include <memory> #include <utility> // 用于std::forward struct Deleter { void operator() (A* a) {} }; class A { A(int a) {} // 友元自定义函数,让它能访问私有构造函数 template<typename T, typename Del, typename... Args> friend std::unique_ptr<T, Del> make_unique_with_deleter(Args&&... args); }; template<typename T, typename Deleter, typename... Args> std::unique_ptr<T, Deleter> make_unique_with_deleter(Args&&... args) { // 完美转发构造函数参数,同时创建带自定义删除器的unique_ptr return std::unique_ptr<T, Deleter>(new T(std::forward<Args>(args)...), Deleter()); } int main() { auto unique = make_unique_with_deleter<A, Deleter>(5); }
额外注意点
你的代码里A的构造函数是私有成员,不管用哪种方式,都需要让创建对象的代码(main或者自定义的make_unique_with_deleter)拥有访问权限,否则会触发编译错误——上面的示例里已经通过friend声明解决了这个问题。
内容的提问来源于stack exchange,提问作者AathakA
相关产品推荐
相关产品推荐

