深拷贝和浅拷贝有什么区别?
广度 vs 深度;以您的对象为根节点,将其看作引用树。
浅复制:
变量A和B引用不同的内存区域,当将B赋值给A时,两个变量引用相同的内存区域。稍后对其中任何一个的内容进行修改都会立即反映在另一个的内容中,因为它们共享内容。
深复制:
变量A和B引用不同的内存区域,当将B赋值给A时,A指向的内存区域的值被复制到B指向的内存区域。稍后对其中任何一个的内容进行修改都只会影响到该变量本身的内容,而不会影响到另一个变量,它们的内容没有共享关系。
浅复制尽可能少地复制。集合的浅复制是集合结构的一个副本,而不是元素。通过浅复制,两个集合现在共享各自的元素。
深复制复制一切。集合的深复制是对原始集合中所有元素进行复制的两个集合。
Address
对象的 Customer
对象,则“按位”复制 Customer
对象意味着Address
对象的指针/引用被复制。原始和副本都指向相同的 Address
对象,而深层复制将创建一个新的 Address
对象并指向该对象。 - Raphael Schmitz特别针对iOS开发者:
如果B
是A
的浅复制,那么对于原始数据,它就像B = [A assign];
,对于对象,它就像B = [A retain]
;
B和A指向同一内存位置。
如果B
是A
的深复制,那么它就像B = [A copy];
B和A指向不同的内存位置。
B的内存地址与A相同。
B具有与A相同的内容。
浅拷贝:将一个对象的成员变量值复制到另一个对象中。
深拷贝:将一个对象的成员变量值复制到另一个对象中。
任何指针对象都会被复制并进行深度拷贝。
示例:
class String
{
int size;
char* data;
};
String s1("Ace"); // s1.size = 3 s1.data=0x0000F000
String s2 = shallowCopy(s1);
// s2.size =3 s2.data = 0X0000F000
String s3 = deepCopy(s1);
// s3.size =3 s3.data = 0x0000F00F
// (With Ace copied to this location.)
我在这里没有看到简短易懂的答案,所以我来试试。
浅复制会使目标对象也指向源对象指向的任何对象(因此不会复制任何引用的对象)。
深复制会复制源对象指向的任何对象,并且将该副本指向目标对象(因此每个引用对象现在都有两个)。 这个过程会递归地下降到对象树中。
{想象两个对象:A和B是相同类型_t(就C++而言),你正在考虑将A浅复制/深复制到B}
浅复制: 简单地将A的引用复制到B。可以将其视为A地址的副本。 因此,A和B的地址将相同,即它们将指向相同的内存位置,即数据内容。
深复制: 简单地复制A的所有成员,在不同的位置为B分配内存,然后将复制的成员赋值给B以实现深复制。这样,即使A不存在,B在内存中仍然有效。正确的术语应该是克隆,你知道它们完全相同,但又不同(即在内存空间中存储为两个不同的实体)。在进行深复制时,你还可以提供克隆包装器,在其中可以通过包含/排除列表来决定选择哪些属性。这在创建API时是一种常见做法。
只有在你理解所涉及的风险时,才可以选择进行浅复制。仅当在C++或C中处理大量指针时,对对象进行浅复制真的是一个非常糟糕的主意。
深拷贝的例子 一个例子是,在进行图像处理和物体识别时,您需要将“无关和重复的动作”屏蔽在处理区域之外。如果您使用图像指针,那么您可能有保存这些掩码图像的规范。现在...如果您对图像进行浅拷贝,当指针引用从堆栈中删除时,您将丢失引用及其副本,即在某个时刻将出现运行时错误的访问冲突。在这种情况下,您需要通过克隆来进行深拷贝以获取图像。这样,如果将来需要,您可以检索掩码。
浅拷贝的例子 我真的认为如果您知道您的程序将无限期运行,即在堆栈上进行连续的“推-弹”操作和函数调用,那么进行浅拷贝不是一个好主意。如果您正在向一个业余或初学者展示某些东西(例如C/C++教程内容),那么可能还可以。但是,如果您正在运行诸如监视和检测系统或声纳跟踪系统之类的应用程序,您不应该在对象之间进行浅拷贝,因为这将迟早导致程序崩溃。
什么是浅拷贝?
浅拷贝是对象的按位复制。创建一个新对象,该对象具有原始对象中的值的精确副本。如果对象的任何字段是对其他对象的引用,则仅复制引用地址,即仅复制内存地址。
在此图中,MainObject1
具有类型为int的field1
和类型为ContainObject
的ContainObject1
字段。当您对MainObject1
进行浅拷贝时,将使用field1
的复制值创建MainObject2
,并仍指向ContainObject1
本身。请注意,由于field1
是基本类型,因此其值复制到field2
,但由于ContainedObject1
是对象,因此MainObject2
仍然指向ContainObject1
。因此,在MainObject1
中对ContainObject1
所做的任何更改都将反映在MainObject2
中。
现在如果这是浅拷贝,那么深度拷贝又是什么呢?
什么是深拷贝?
深度拷贝是指复制所有字段,并复制字段所指向的动态分配内存的副本。当一个对象被复制以及它所引用的对象时,就会发生深拷贝。
在这个示例中,MainObject1具有类型为int的field1和类型为ContainObject的ContainObject1字段。当您对MainObject1进行深层复制时,将创建MainObject2,其中field2包含field1的复制值,ContainObject2包含ContainObject1的复制值。请注意,对MainObject1中的ContainObject1所做的任何更改都不会反映在MainObject2中。好文章field3
的字段,但是这并不是你的错。当试图理解这样深奥的问题时,我们需要知道在ContainObject2
中,这个#3是什么意思? - Robb_2015