You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为成员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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:55:28