为成员std::unique_ptr实现访问类成员的自定义删除器
解决std::unique_ptr自定义删除器访问类allocator成员的不完整类型问题
问题根源
在entity类内部声明std::unique_ptr时,类本身仍属于不完整类型。如果自定义删除器直接尝试访问entity的allocator_成员,编译器无法解析类的完整结构,因此触发"不完整类型"错误。
无需std::function的两种解决方案
方案1:删除器持有allocator拷贝(推荐)
std::pmr::polymorphic_allocator是轻量级的拷贝类型,拷贝后会共享同一个内存资源,完全满足"使用同一个分配器"的需求。让删除器持有allocator的拷贝,无需依赖entity类的完整类型。
#include <memory> #include <memory_resource> // 前置声明资源类 class Resource; // 通用PMR删除器 template <typename T> struct PmrDeleter { std::pmr::polymorphic_allocator<T> alloc; void operator()(T* ptr) const { if (ptr) { alloc.delete_object(ptr); } } }; class entity { private: std::pmr::polymorphic_allocator<char> allocator_; using ResourcePtr = std::unique_ptr<Resource, PmrDeleter<Resource>>; ResourcePtr resource_; public: explicit entity(std::pmr::polymorphic_allocator<char> alloc) : allocator_(alloc), // 拷贝allocator到删除器中,确保使用同一资源 resource_(allocator_.new_object<Resource>(), PmrDeleter<Resource>{allocator_}) {} };
方案2:嵌套删除器+类外定义operator()
如果必须直接访问entity的allocator_成员,可以将删除器定义为entity的嵌套类,仅在类内声明operator(),等到类定义完成后再在外部实现该方法(此时entity已成为完整类型)。
#include <memory> #include <memory_resource> // 前置声明资源类 class Resource; class entity { private: std::pmr::polymorphic_allocator<char> allocator_; // 嵌套删除器,仅声明operator() struct Deleter { void operator()(Resource* ptr) const; entity* self; // 持有entity指针以访问allocator_ }; using ResourcePtr = std::unique_ptr<Resource, Deleter>; ResourcePtr resource_; public: explicit entity(std::pmr::polymorphic_allocator<char> alloc) : allocator_(alloc), resource_(allocator_.new_object<Resource>(), Deleter{this}) {} }; // 类外定义operator(),此时entity已是完整类型 void entity::Deleter::operator()(Resource* ptr) const { if (ptr) { self->allocator_.delete_object(ptr); } }
方案对比
- 方案1:代码更通用,无类依赖,避免悬空指针风险(
pmr::polymorphic_allocator拷贝成本可忽略),优先推荐。 - 方案2:无需拷贝allocator,但删除器依赖
entity类,需确保self指针在删除器执行时有效(本场景中resource_是entity成员,生命周期绑定,因此安全)。
内容的提问来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

