Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
深度复制包含引用成员的结构(C+;+;) 我有C++类,它包含指向指向类内其他对象的引用成员的对象。这在当时似乎是个好主意,但现在我需要实现整个过程的深层次复制,我看不到一种不让人觉得笨拙的方法_C++_Deep Copy - Fatal编程技术网

深度复制包含引用成员的结构(C+;+;) 我有C++类,它包含指向指向类内其他对象的引用成员的对象。这在当时似乎是个好主意,但现在我需要实现整个过程的深层次复制,我看不到一种不让人觉得笨拙的方法

深度复制包含引用成员的结构(C+;+;) 我有C++类,它包含指向指向类内其他对象的引用成员的对象。这在当时似乎是个好主意,但现在我需要实现整个过程的深层次复制,我看不到一种不让人觉得笨拙的方法,c++,deep-copy,C++,Deep Copy,我的代码的简化版本如下所示。问题在于为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 {

我的代码的简化版本如下所示。问题在于为
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_数组
中项目的参考成员指向
c_数组
中项目的要求,但除此之外,数据可以是任何内容。复制构造函数对满足此属性的任何数据都有效,这一点很重要。这不是一个可以通过重用现有初始化代码来解决的问题

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

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

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

  • 使用此索引初始化新
    b_数组的相应元素的引用成员

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


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

使用引用的深度复制必须首先复制值(c_数组),然后存储对这些新值的引用。除了您描述的算法之外,我看不到实现这一点的方法

使用指针而不是引用不会改变这一点。有很多种。指针初始化起来不那么棘手(创建为null并在准备就绪时赋值),使用起来更危险(可能仍然为null)。但是您仍然需要复制对象,然后查找并复制指向它们的链接


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

您可以为
a
提供赋值运算符(和复制选择器),该运算符处理
c_数组
b_数组
的串联更改,假设
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;
    }
};
有点乱,但是:


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

有趣的问题!我看到的所有“深度复制”问题在编译时都有已知的引用结构,并在复制逻辑中进行了硬编码。能否用一个映射替换b_数组和c_数组?@GrahamGriffiths我的实际
b
类存储对
c_数组
成员的多个引用。我想它可以实现为几个
map
s,但是真正的
B
是一个实现其他代码的类层次结构,因此重新考虑会有点棘手。(我也倾向于避免使用STL代码,我想这主要是出于习惯。)如果不了解当前如何初始化这些数组,就很难给出任何具体的建议,即复制构造函数需要初始化副本,并且您有一些现有的代码来初始化原件。所有重要的细节都在评论中一点一滴地出现,这使得人们很难猜测解决方案需要提供什么,或者现有的解决方案是什么(未显示)代码它可以重用数组索引的唯一问题是,如果我将
c_array
替换为更易变的东西,如
std::list
,那么当其内容更改时,所有索引都必须更新,如果它们不同步,则很难跟踪错误。(目前我的代码没有做到这一点,但我可能很想在将来做到。)当然,我现在看到,基于引用成员的实现也有引入滑错误的方法。你的答案可能是对的,但如果有人有一个聪明的解决方案,我会保留它。我认为指针算法比
std::find
好,因为
std::find
必须进行线性搜索,而指针算法可以在一次操作中告诉我答案。我已经有了内存地址,所以我不需要搜索元素,只要从
c\u数组
指针的值中减去它就行了。谢谢,这是个好主意,但不幸的是,在我的情况下,这是不可能的,因为
B
包含对a
c
的多个引用以及其他数据。(我曾试图将问题简化为最简单的版本,但现在我意识到我应该明确指出,
B
包含其他数据-我已经更新了问题中的示例代码。对此表示抱歉。)可以理解,
B
包含其他数据,但这正是
B
的普通赋值运算符和复制构造函数的作用。我的观点是,在您实现了op和copy-ctor之后,再进行一些后续操作