深度复制包含引用成员的结构(C ++)

时间:2014-03-05 09:40:19

标签: c++ deep-copy

我有一个C ++类,它包含具有指向类中其他对象的引用成员的对象。这在当时似乎是一个好主意,但现在我需要实现整个事情的深层副本,我无法看到一种不那么笨重的黑客的方法。

我的代码的简化版本如下所示。问题是关于为A编写复制构造函数。

class C {
    int x, y, z; // nothing complicated stored in this class
public:
    // constructor and other methods
};

class B {
    C &c1;
    C &c2;
public:
    // constructor and other methods
};

class A {
    C *c_array;
    B *b_array; // for each item in this array, 
                // its 'c1' and 'c2' fields point to members of c_array.
public:
    // constructor and other methods
};

有些人问过这个结构是如何初始化的,所以请允许我强调这与回答这个问题无关。初始化将始终满足b_array中项目的参考成员指向c_array中的项目的要求,但除此之外,数据可以是任何内容。复制构造函数必须适用于满足此属性的任何数据。这不是可以通过重用现有的初始化代码来解决的问题。

问题是如果我只是复制b_array中的对象,他们的引用成员将指向C实例中的A个对象。我需要让它们指向 new 实例中的相应项。我能想到的唯一方法就是:

  • 对于b_array的每个元素,获取其引用成员指向的地址,并将其存储在指针中

  • 将索引计算到该指针对应的数组中使用指针算法

  • 使用此索引初始化新b_array的相应元素的引用成员。

我的问题是,是否有更干净/更简单/更优雅的方式?如果没有,我将重构我的设计以使用数组索引而不是整个引用。

也许我不应该使用引用成员 - 我知道有些人说使用指针总是更好。如果我使用指针而不是引用,那么这个问题会有更好的解决方案吗? (我看不到一个,但我不知道。)

2 个答案:

答案 0 :(得分:1)

使用引用的深层复制必须首先复制值(c_array),然后存储对这些新值的引用。除了你描述的算法之外,我无法看到实现这一目标的方法。

使用指针而不是引用不会改变这一点。有各种comparisons of pointers vs references。指针初始化时不那么棘手(创建为null并在准备好时分配)并且使用起来更危险(可能仍为null)。但是你仍然需要复制对象,然后找到+复制链接到它们。

我看不到比使用数组索引更简单/更优雅的方式。使用数组索引,您只需按值复制数组值,并使用哪个索引的结构指向将为您处理的对象。

答案 1 :(得分:1)

您可以为A提供一个指派运算符(和副本ctor),它同时处理c_arrayb_array的变化,假设B可以处理C的赋值仅作为引用/指针更新。

它可以是:

struct B { ... B& operator=(const C& c) { this->c = &c; return *this; } };

struct A { ...
    A& operator=(const A& a) {
        c_array = a.c_array;
        b_array = a.b_array;
        // re-assign pointers/references only using B's `operator=(const C&)` :
        std::copy_n(c_array.begin(), c_array.size(), b_array.begin());
        return *this;
    }
};

有点乱,但是:see live example

请注意,如果您注释掉std::copy_n行,您当然可以在输出中观察到副本没有分离,也就是说,副本的b_array指向原始版本{ {1}}而不是自己的。