含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
相关产品推荐
相关产品推荐

