C ++何时执行深层复制和浅层复制?

时间:2018-09-11 10:13:55

标签: c++

我想知道C ++何时进行深度复制,何时进行深度复制。

例如:

src/

为了在移出函数后删除n,它必须创建一个临时变量n,并将其返回给调用方。结果,那是浅表副本,对吗?

3 个答案:

答案 0 :(得分:4)

  

因此,那是浅表副本,对吗?

浅表副本始终引用原始对象所引用的内容。深层副本是指所引用资源的副本††(该资源的新副本必须由副本构造函数创建)。仅当复制的对象是引用对象(即它引用某种资源)时,这种区别才有意义。

int类型不引用任何对象,因此就类型系统而言,它不是引用的。但是在类型系统之外,可以给它提供参考意义。例如,用整数表示资源(例如存储在数据库中的实体)的身份是非常典型的。您需要考虑整数是否是这种情况。在面向对象的设计中,此类标识符通常包装在一个类中,该类可以指定为支持深层副本。

非类类型的副本总是很浅。只有复制构造函数††††可以执行深层复制。如果5标识某些资源,则副本5也将引用同一资源。

与深层复制和浅层复制相关的引用类型的示例:引用,指针,具有引用成员的类。 usch类的示例:智能指针,引用标识符的包装†††。在这些指针和引用中,它们不是类,因此会被浅表复制。根据复制构造函数的实现,类实例的复制可能浅或深。

然后是移动结构。移动构造是一个浅表副本,它以强制任何平凡的浅表副本会违反的类不变式的方式修改原始对象。例如,唯一指针的move构造函数将浅表复制内部指针,并将原始指针设置为null,以保持指针所有权的唯一性。


为简单起见,我说的是对象,但这也适用于引用类型的副本-也不是对象。

††资源可能是内存中的另一个对象,例如文件描述符或执行线程。

†††示例:std::thread包含操作系统提供的较低级别的标识符。

††††任何函数都可以执行深层复制,但是复制构造函数是唯一由复制初始化调用的函数。

答案 1 :(得分:2)

int不是引用类型,因此不存在浅拷贝或深拷贝问题。它只是一个副本。

我们可以理解以下的深层和浅层副本:

深拷贝

深层副本将复制所有字段,并复制这些字段所指向的动态分配的内存。当复制对象及其引用的对象时,就会发生深层复制。

浅拷贝

浅表副本是对象的按位副本。创建一个新对象,该对象具有原始对象中值的精确副本。如果对象的任何字段是对其他对象的引用,则仅复制引用地址,即仅复制内存地址,而不复制实际对象。

答案 2 :(得分:2)

通常将术语“浅拷贝”和“深拷贝”理解为自身间接封装某些对象的类型。

例如,一个带有指针的类(我们假设它指向某物):

struct Foo
{
   Bar* ptr;
};

复制Foo时,它也指向复制的Bar吗( deep )?还是新的Foo仅共享指向原始Bar的原始指针()?

这取决于复制的执行方式-通常,您的Foo将具有一个复制构造函数,而这个复制构造函数中的代码才有区别。

例如,所有标准C ++容器(例如vector)在内部都是由指向某些已分配缓冲区的指针组成的,但是它们具有复制构造函数,可确保在复制向量时复制整个缓冲区,这样每个向量都有其 own 独立缓冲区。这是一个深层副本。

但是我上面给出的示例,没有任何复制构造函数或其他可爱的代码,在分配时将仅执行浅表复制,因为除了复制ptr的值外,我没有告诉它做任何事情

对于您的情况:int只是一个值,因此我们无法进行这种比较。您只有简单而简单的值副本。实现该功能需要多少个临时人员的内部细节是无关紧要的(无关紧要);在这种情况下,谈论浅拷贝与深拷贝是没有意义的,因为从字面上看,没有封装的,间接拥有的对象拥有或不拥有的对象,可以被视为浅或深或任何复制。我们通常可以对任何非类类型说这种话。