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

如何实现删除vector中std::shared_ptr时同步删除unordered_map中指向同一对象的指针——自定义shared_ptr删除器的编写方法

这个需求很有意思,核心是要让vector里的shared_ptr销毁时自动同步清理unordered_map里的对应条目,保证两者的一致性。咱们一步步来实现这个自定义删除器,顺便聊聊设计上的关键细节。

首先得明确几个核心逻辑:

  1. 删除器需要能访问到World类里的organisms_map,所以得让它能拿到World的实例引用。
  2. 删除器要知道该从map里移除哪个键,所以每个Organism得关联对应的坐标键,或者创建shared_ptr时把键传给删除器。
  3. 要满足“不在animals_vector中的对象必然不在organisms_map中”,map里不能持有强引用——不然就算vector里的shared_ptr被移除,map的强引用会让对象继续存活,破坏一致性。所以map应该存weak_ptr而非shared_ptr。

第一步:给Organism添加键成员

先给Organism加个成员变量存储对应的坐标键,这样删除器能直接从对象拿到要移除的键:

class Organism {
public:
    int m_key; // 存储转换后的坐标int值,和map的键严格对应
    // 你的其他成员和业务逻辑...
};

第二步:实现带自定义删除器的shared_ptr创建

在World的add_organism方法里,创建Organism实例时构造shared_ptr并传入自定义删除器。这个删除器用lambda捕获World的this指针,从而能直接操作organisms_map:

class World {
private:
    unordered_map<int, std::weak_ptr<Organism>> organisms_map; // 改用weak_ptr避免强引用
    vector<std::shared_ptr<Organism>> animals_vector;

public:
    void add_organism(int key) {
        // 创建Organism实例并设置对应键
        auto* organism = new Organism();
        organism->m_key = key;

        // 构造带自定义删除器的shared_ptr
        std::shared_ptr<Organism> org_ptr(organism, [this](Organism* ptr) {
            // 1. 先从map中移除对应的条目
            organisms_map.erase(ptr->m_key);
            // 2. 再销毁Organism对象
            delete ptr;
        });

        // 将shared_ptr加入vector,同时给map存对应的weak_ptr
        animals_vector.push_back(org_ptr);
        organisms_map[key] = org_ptr;
    }

    // 示例:从map中查找有效对象的方法
    std::shared_ptr<Organism> find_organism(int key) {
        auto it = organisms_map.find(key);
        if (it != organisms_map.end()) {
            auto sp = it->second.lock(); // 尝试获取强引用,检查是否过期
            if (sp) {
                return sp;
            }
            // 如果weak_ptr已过期,顺便清理map里的无效条目
            organisms_map.erase(it);
        }
        return nullptr;
    }
};

设计逻辑说明

  • 删除器的作用:当vector里的shared_ptr被销毁(比如vector被清空、元素被移除且无其他强引用),引用计数降为0,触发删除器。删除器先从map里移除对应键,再销毁Organism对象,完美同步两者的状态。
  • 用weak_ptr存map:这样map不会持有对象的强引用,对象的生命周期完全由vector里的shared_ptr控制。只要vector里没了对象,map里的weak_ptr会过期,我们可以在查找时清理无效条目,或者定期维护。

注意事项

  1. 线程安全:如果是多线程环境,对organisms_map和animals_vector的所有操作要加锁(比如用std::mutex),避免并发修改导致的未定义行为。
  2. 键的一致性:必须确保Organism::m_key和map的键完全一致,否则删除器会移除错误的条目。
  3. 避免悬空引用:不要在World外部保存Organism的裸指针或强引用,不然会破坏“vector是唯一强引用源”的设计逻辑。

内容的提问来源于stack exchange,提问作者Michał Turek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:12:29