如何创建带有自定义删除器的unique_ptr数组?
如何创建带有自定义删除器的unique_ptr数组?
你遇到的问题核心在于:带捕获外部变量的lambda作为自定义删除器的std::unique_ptr,是没有默认构造函数的——因为lambda捕获了allocator,它的类型天生不支持默认构造,而std::array默认初始化时会尝试给每个元素调用默认构造,这就直接触发了编译错误。
下面给你几个实用的解决办法:
方法一:改用可默认构造的删除器类型
把lambda替换成一个可以默认构造的 functor 类,这样unique_ptr就能支持默认构造了,自然也能放进std::array里:
#include <cstdio> #include <memory_resource> #include <memory> #include <string_view> #include <array> #include <utility> /* declval */ struct msg_outbound_t { std::string_view hello_ = "Hello World!"; }; using allocator_t = std::pmr::polymorphic_allocator<std::byte>; // 自定义删除器类,默认构造时使用空的allocator struct pmr_deleter { allocator_t allocator{}; void operator()(msg_outbound_t* p) const { if (p) { // 避免空指针操作 allocator.delete_object(p); } } }; // 现在msg_handle_t支持默认构造了 using msg_handle_t = std::unique_ptr<msg_outbound_t, pmr_deleter>; int main() { std::array<msg_handle_t, 8> myarray; // 正常编译 }
这个方法最简洁,也符合固定大小数组的需求。
方法二:手动初始化数组的每个元素
如果不想修改删除器的定义,可以给std::array提供初始化列表,用一个默认的删除器实例来构造每个空的unique_ptr:
int main() { // 创建一个默认的删除器实例 auto default_deleter = pmr_deleter(allocator_t{}); // 手动初始化每个元素 std::array<msg_handle_t, 8> myarray{ msg_handle_t{nullptr, default_deleter}, msg_handle_t{nullptr, default_deleter}, msg_handle_t{nullptr, default_deleter}, msg_handle_t{nullptr, default_deleter}, msg_handle_t{nullptr, default_deleter}, msg_handle_t{nullptr, default_deleter}, msg_handle_t{nullptr, default_deleter}, msg_handle_t{nullptr, default_deleter} }; }
缺点是元素多的时候写起来麻烦,但适合临时场景。
方法三:改用std::vector动态容器
如果对容器类型没有严格要求,用std::vector配合resize来批量初始化会更方便:
int main() { auto default_deleter = pmr_deleter(allocator_t{}); std::vector<msg_handle_t> myvec; // 批量初始化8个空的unique_ptr myvec.resize(8, msg_handle_t{nullptr, default_deleter}); }
vector是动态扩容的,但使用起来比手动写array初始化列表省事。
总结一下,优先推荐方法一,它从根源上解决了默认构造的问题,代码也最干净。
备注:内容来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

