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

含std::unordered_map<unique_ptr>的对象深拷贝方案咨询

解决包含不可拷贝类的深拷贝问题

我完全懂你的处境——要深拷贝类型A,但它依赖的类B因为内部持有std::unordered_map<..., std::unique_ptr<C>>而天生不可拷贝,而且你不想破坏B的封装或者强行添加拷贝构造/赋值。更麻烦的是unique_ptr指向的是基类C的派生类,每个派生类成员都不一样,得处理多态下的深拷贝。

下面是贴合你需求的具体实现方案:

1. 给基类C添加纯虚克隆方法

要深拷贝多态对象,最经典的做法就是用克隆模式,让每个派生类自己负责创建自身的副本:

class C {
public:
    virtual ~C() = default;
    // 纯虚克隆方法,所有派生类必须实现
    virtual std::unique_ptr<C> clone() const = 0;
};

// 示例派生类D
class D : public C {
private:
    int custom_data;
public:
    D(int data) : custom_data(data) {}
    std::unique_ptr<C> clone() const override {
        // 返回当前D对象的深拷贝,用unique_ptr管理
        return std::make_unique<D>(*this);
    }
};

// 另一个示例派生类E
class E : public C {
private:
    std::string custom_str;
public:
    E(const std::string& str) : custom_str(str) {}
    std::unique_ptr<C> clone() const override {
        return std::make_unique<E>(*this);
    }
};

2. 给类B添加自定义深拷贝函数

既然不想给B加拷贝构造,我们可以写一个成员函数专门生成B的深拷贝实例:

class B {
private:
    std::unordered_map<int, std::unique_ptr<C>> internal_map;
public:
    // 保留移动构造/赋值,不影响原有逻辑
    B(B&&) = default;
    B& operator=(B&&) = default;

    // 自定义深拷贝函数,返回B的智能指针
    std::unique_ptr<B> deep_copy() const {
        auto new_b = std::make_unique<B>();
        // 遍历原map,对每个unique_ptr调用clone()生成新对象
        for (const auto& pair : internal_map) {
            new_b->internal_map.emplace(pair.first, pair.second->clone());
        }
        return new_b;
    }

    // 其他业务方法示例
    void add_item(int key, std::unique_ptr<C> value) {
        internal_map.emplace(key, std::move(value));
    }
};

3. 实现类型A的深拷贝

现在A里的std::vector<B>可以通过调用每个B的deep_copy()完成深拷贝:

class A {
private:
    std::vector<B> b_vector;
public:
    // 自定义深拷贝构造函数
    A(const A& other) {
        b_vector.reserve(other.b_vector.size());
        for (const auto& b : other.b_vector) {
            // 调用B的deep_copy,然后移动到vector中
            b_vector.push_back(std::move(*b.deep_copy()));
        }
    }

    // 用拷贝交换惯写法实现深拷贝赋值
    A& operator=(A other) {
        std::swap(b_vector, other.b_vector);
        return *this;
    }

    // 默认生成移动构造/赋值
    A(A&&) = default;
    A& operator=(A&&) = default;

    // 业务方法示例
    void add_b(B b) {
        b_vector.push_back(std::move(b));
    }
};

方案优势

  • 完全没给B添加拷贝构造/赋值,保持了它的不可拷贝特性(默认拷贝构造会被编译器删除)
  • 克隆模式完美解决了多态对象的深拷贝问题,每个派生类自主管理副本创建,类型安全
  • 整个实现逻辑清晰,没有冗余代码,也不需要任何强制类型转换

内容的提问来源于stack exchange,提问作者user7431005

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:00:45