如何实现引用计数为1时自动移回free_buffer的shared_ptr对象工厂?
解决方案
要实现当外部不再持有对象引用时自动将其移回预分配缓冲区,核心是利用std::shared_ptr的自定义删除器特性,让删除器负责对象的回收逻辑而非销毁对象(因为是预分配复用)。同时调整工厂内部的缓冲区存储方式,避免额外的引用计数干扰。
核心思路
- 预分配的对象存储在
free_buffer中,使用原始指针或带空删除器的智能指针(避免误销毁)。 - 调用
get_object()时,从free_buffer取出对象,存入used_buffer跟踪正在使用的对象。 - 返回给调用者的
std::shared_ptr<A>绑定自定义删除器:当最后一个外部引用销毁时,删除器触发,将对象从used_buffer移除并放回free_buffer,全程无需调用者干预。
代码实现
基础版本(使用原始指针)
#include <vector> #include <memory> #include <stdexcept> #include <algorithm> class A { // 类A的自定义实现 }; class ObjectFactory { public: // 构造时预分配指定数量的对象 ObjectFactory(size_t preallocate_count) { for (size_t i = 0; i < preallocate_count; ++i) { free_buffer.push_back(new A()); } } // 析构时销毁所有预分配对象 ~ObjectFactory() { for (A* ptr : free_buffer) { delete ptr; } for (A* ptr : used_buffer) { delete ptr; } } std::shared_ptr<A> get_object() { if (free_buffer.empty()) { throw std::runtime_error("No free objects available in factory"); } // 从空闲缓冲区取出对象 A* raw_ptr = free_buffer.back(); free_buffer.pop_back(); // 标记为已使用 used_buffer.push_back(raw_ptr); // 返回绑定自定义删除器的shared_ptr return std::shared_ptr<A>(raw_ptr, [this](A* ptr) { // 从已使用缓冲区移除 auto it = std::find(used_buffer.begin(), used_buffer.end(), ptr); if (it != used_buffer.end()) { used_buffer.erase(it); } // 放回空闲缓冲区 free_buffer.push_back(ptr); // 不销毁对象,留待复用 }); } private: std::vector<A*> used_buffer; std::vector<A*> free_buffer; };
安全改进版本(使用带空删除器的unique_ptr)
为避免原始指针的误用,可使用自定义删除器的unique_ptr管理预分配对象,确保只有工厂析构时才销毁对象:
#include <vector> #include <memory> #include <stdexcept> #include <algorithm> class A { // 类A的自定义实现 }; // 自定义unique_ptr,删除器为空操作,避免误销毁对象 using ReusableA = std::unique_ptr<A, void(*)(A*)>; class ObjectFactory { public: ObjectFactory(size_t preallocate_count) { auto noop_deleter = [](A*) {}; // 空删除器,仅占位不执行销毁 for (size_t i = 0; i < preallocate_count; ++i) { free_buffer.emplace_back(new A(), noop_deleter); } } ~ObjectFactory() { // 手动销毁所有对象 for (auto& ptr : free_buffer) { delete ptr.release(); } for (A* ptr : used_buffer) { delete ptr; } } std::shared_ptr<A> get_object() { if (free_buffer.empty()) { throw std::runtime_error("No free objects available in factory"); } // 移动取出空闲对象 ReusableA reusable_obj = std::move(free_buffer.back()); free_buffer.pop_back(); A* raw_ptr = reusable_obj.get(); used_buffer.push_back(raw_ptr); // 返回shared_ptr,删除器负责将对象放回缓冲区 return std::shared_ptr<A>(raw_ptr, [this, obj = std::move(reusable_obj)](A*) mutable { // 从已使用缓冲区移除 auto it = std::find(used_buffer.begin(), used_buffer.end(), obj.get()); if (it != used_buffer.end()) { used_buffer.erase(it); } // 放回空闲缓冲区 free_buffer.push_back(std::move(obj)); }); } private: std::vector<A*> used_buffer; std::vector<ReusableA> free_buffer; };
关键说明
- 自定义删除器仅在最后一个外部
shared_ptr销毁时触发,确保对象不再被外部使用后才回收。 - 工厂内部的
used_buffer仅存储原始指针(或不增加引用计数的智能指针),避免干扰引用计数逻辑。 - 若需多线程安全,只需给
used_buffer和free_buffer的操作添加std::mutex保护即可。
内容的提问来源于stack exchange,提问作者majvan
相关产品推荐
相关产品推荐

