【问题标题】:deep copy of objects containing unordered_map of unique_ptr包含 unordered_map 的 unique_ptr 的对象的深层副本
【发布时间】:2018-04-08 15:40:05
【问题描述】:

我有以下情况:

我需要从A 类型创建一个变量的深层 (!) 副本。该变量包含一个B 类型的向量。 B 类不可复制,因为它包含一个 std::unordered_map,其值为 unique_ptr(不可复制)。我想避免通过复制构造函数或复制赋值运算符使B 可复制。

一个问题是unique_ptr 的类型只是基本类型。实际对象派生自C,包含不同的成员和不同的构造函数。

class A{
public:
    A(const A&);            // how should I implement this?
    A& operator=(const A&); // how should I implement this?
private:
    vector<B> vectorOfB;
}

class B{
private:
    std::unordered_map<std::string, std::unique_ptr<C> mapOfDerivedTypesOfC;
}

class C{}

class C_1: public C{
public:
    C_1(double x)
}

class C_2: public C{    
public:
    C_2(double y, double z)
}

背景: A 类的目的是读取大量带有数据的大型文本文件并创建许多对象。 之后我必须使用这些对象运行蒙特卡罗模拟。对于每个模拟,我都需要一个 A 的新副本。 我不想每次都读入所有文本文件,因为这很耗时。因此,有必要对 A 进行深层复制。在一次模拟中,我想避免复制 B,因为复制该对象是没有意义的。我认为使用 sharded_ptr 没有帮助,因为我需要一个深拷贝,并且模拟使用 openMP 并行运行。

编辑: 我认为总体问题是我应该如何复制 unordered_map

【问题讨论】:

  • 那么,您的问题到底是什么?
  • B 需要被复制,但您不想对其进行复制操作。这有什么意义?
  • 这个想法是,在一次模拟中,B 不应该被复制。我只需要为每个蒙特卡罗模拟复制A

标签: c++ copy smart-pointers unique-ptr deep-copy


【解决方案1】:

我认为该技术被称为“虚拟复制构造函数”:

// in baseclass
public:
unique_ptr<Base> clone() const
{
    unique_ptr<Base> other(this->do_clone());
    assert(typeid(*this) == typeid(*other));
    return other;
}
private:
virtual Base* do_clone() const = 0;

// in derived class
private:
virtual Derived* do_clone() const
{
    return new Derived(*this);
}

这个想法是,一个类型最终会知道如何克隆它自己的实例,所以你可以通过一个虚函数将克隆委托给它。断言确保派生类正确实现/覆盖基类实现。

【讨论】:

  • assert 应该做什么?
  • 见最后一句:“断言确保派生类正确实现/覆盖基类实现。”
  • 我尝试用你的方法来实现它,非常感谢你的投入。一个问题: do_clone 应该是虚拟的吗?或者=0 对非虚函数有什么作用?
  • 是的,应该是虚拟的。
  • @user7431005 • 该模式称为非虚拟接口模式(NVI)。小项目的矫枉过正,但对大项目非常有用。 en.wikipedia.org/wiki/Non-virtual_interface_pattern
【解决方案2】:

长话短说,您需要在C 中为每个要覆盖的继承类编写一个虚函数。类似的东西

virtual std::unique_ptr<C> anotherOnePlease() = 0;

然后您可以在每个C * 上使用此功能,并创建一个新地图。有点烂,但如果你为每个派生的C 实现这个函数,至少你可以编写一个稍微简单的函数来复制地图。

【讨论】:

  • 如果我这样做,我从C_1 的返回类型需要是C_1 而不是C。这可能吗?
  • 您可以将C_1 * 转换为C *,因为它是指向基类的指针。只要C_1 派生自C 就可以了。请注意,这仅适用于指针,而不适用于值。这与您可以将它们一起存储在地图中的原因相同。
  • 当然你也应该使用std::unqiue_ptr&lt;C&gt;而不是C *,因为它更短,我就这样写。
  • 好的,我想我理解你的方法。我会尝试像这样实现它。
猜你喜欢
  • 2012-01-21
  • 2011-12-09
  • 2021-11-06
  • 2016-02-15
  • 2015-12-28
  • 1970-01-01
  • 2013-04-09
相关资源
最近更新 更多