如何从内存池返回带自定义删除器、指向抽象类型的std::unique_ptr
问题根源
编译失败的核心原因是std::unique_ptr的删除器属于其类型签名的一部分,代码中原定义的std::unique_ptr<Test, std::function<void(Test*)>>与ITestOwner中使用默认删除器的std::unique_ptr<ITest>是完全不兼容的两种类型,无法直接转移所有权。
可行实现方案
通过调整ITestOwner的智能指针定义,使用类型擦除的std::function作为删除器,同时封装自定义删除逻辑适配基类指针,即可实现需求。修改后可正常运行的完整代码如下:
#include <iostream> #include <memory> #include <functional> #include <utility> template <typename T> class MemoryPool { public: template <typename ... ARGS> T* create(ARGS&&... args) { std::cout << "MemoryPool::create()" << std::endl; return new T(std::forward<ARGS>(args)...); } void destroy(T* ptr) { std::cout << "MemoryPool::destroy()" << std::endl; delete ptr; } }; class ITest { public: ITest() { std::cout << "ITest::ITest()" << std::endl; } virtual ~ITest() { std::cout << "ITest::~ITest()" << std::endl; } virtual void sayHello() = 0; }; class Test :public ITest { public: Test() { std::cout << "Test::Test()" << std::endl; } ~Test() { std::cout << "Test::~Test()" << std::endl; } void sayHello() override { std::cout << "Test says hello" << std::endl; } }; class ITestOwner { public: // 修改构造函数参数类型,使用带类型擦除删除器的unique_ptr ITestOwner(std::unique_ptr<ITest, std::function<void(ITest*)>> ptr) : _ptr(std::move(ptr)) { std::cout << "ITestOwner::ITestOwner()" << std::endl; } ~ITestOwner() { std::cout << "ITestOwner::~ITestOwner()" << std::endl; } void sayHello() { _ptr->sayHello(); } private: // 修改成员变量类型 std::unique_ptr<ITest, std::function<void(ITest*)>> _ptr; }; int main() { MemoryPool<Test> pool; // 直接构造指向ITest的unique_ptr,删除器中做安全类型转换 std::unique_ptr<ITest, std::function<void(ITest*)>> ptr(pool.create(), [&pool](ITest* ptr){ std::cout << "Custom Deleter" << std::endl; pool.destroy(static_cast<Test*>(ptr)); }); ITestOwner owner(std::move(ptr)); owner.sayHello(); return 0; }
补充说明
- 因为可以确认传入的
ITest*一定是MemoryPool<Test>分配的Test类实例,所以用static_cast做向下转换是安全的,不需要额外的运行时检查。 - 如果不想修改
ITestOwner的定义,可以替换为std::shared_ptr实现:std::shared_ptr的删除器是类型擦除的,不属于类型签名的一部分,你可以直接构造std::shared_ptr<ITest>并传入自定义删除器,不需要修改持有类的定义。
内容的提问来源于stack exchange,提问作者Patrick Wright
相关产品推荐
相关产品推荐

