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

如何实现引用计数为1时自动移回free_buffer的shared_ptr对象工厂?

解决方案

要实现当外部不再持有对象引用时自动将其移回预分配缓冲区,核心是利用std::shared_ptr的自定义删除器特性,让删除器负责对象的回收逻辑而非销毁对象(因为是预分配复用)。同时调整工厂内部的缓冲区存储方式,避免额外的引用计数干扰。

核心思路

  1. 预分配的对象存储在free_buffer中,使用原始指针或带空删除器的智能指针(避免误销毁)。
  2. 调用get_object()时,从free_buffer取出对象,存入used_buffer跟踪正在使用的对象。
  3. 返回给调用者的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:14:53