我有一个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
的相应元素的引用成员。
我的问题是,是否有更干净/更简单/更优雅的方式?如果没有,我将重构我的设计以使用数组索引而不是整个引用。
也许我不应该使用引用成员 - 我知道有些人说使用指针总是更好。如果我使用指针而不是引用,那么这个问题会有更好的解决方案吗? (我看不到一个,但我不知道。)
答案 0 :(得分:1)
使用引用的深层复制必须首先复制值(c_array),然后存储对这些新值的引用。除了你描述的算法之外,我无法看到实现这一目标的方法。
使用指针而不是引用不会改变这一点。有各种comparisons of pointers vs references。指针初始化时不那么棘手(创建为null并在准备好时分配)并且使用起来更危险(可能仍为null)。但是你仍然需要复制对象,然后找到+复制链接到它们。
我看不到比使用数组索引更简单/更优雅的方式。使用数组索引,您只需按值复制数组值,并使用哪个索引的结构指向将为您处理的对象。
答案 1 :(得分:1)
您可以为A
提供一个指派运算符(和副本ctor),它同时处理c_array
和b_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}}而不是自己的。