【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
深层副本和浅层副本有什么区别?
#1楼
复制Arary:
Array是一个类,这意味着它是引用类型,因此array1 = array2导致两个变量引用同一数组。
但是看这个例子:
static void Main()
{
int[] arr1 = new int[] { 1, 2, 3, 4, 5 };
int[] arr2 = new int[] { 6, 7, 8, 9, 0 };
Console.WriteLine(arr1[2] + " " + arr2[2]);
arr2 = arr1;
Console.WriteLine(arr1[2] + " " + arr2[2]);
arr2 = (int[])arr1.Clone();
arr1[2] = 12;
Console.WriteLine(arr1[2] + " " + arr2[2]);
}
浅克隆表示仅复制由克隆数组表示的内存。
如果数组包含值类型对象,则将值复制 ;
如果数组包含引用类型,则仅复制引用-因此,存在两个成员引用相同对象的数组 。
要创建深层副本(复制引用类型),则必须遍历数组并手动克隆每个元素。
#2楼
特别是对于iOS开发人员:
如果B
是A
的浅表副本 ,那么对于原始数据,它就像B = [A assign];
对于对象,就像B = [A retain]
;
B和A指向相同的存储位置
如果B
是A
的深层副本 ,则类似于B = [A copy];
B和A指向不同的存储位置
B内存地址与A相同
B与A的内容相同
#3楼
{想象两个对象:_t(相对于C ++)类型相同的A和B,您正在考虑将A复制到B的浅层/深层}
浅表复制:将对A的引用简单地复制到B中。将其视为A的地址的副本。 因此,A和B的地址将相同,即它们将指向相同的存储位置,即数据内容。
深层复制:简单地复制A的所有成员,为B分配一个不同位置的内存,然后将复制的成员分配给B以实现深层复制。 这样,如果A不存在,则B在存储器中仍然有效。 正确使用的术语是克隆,即您知道它们完全相同,但又不同(即,作为两个不同的实体存储在内存空间中)。 您还可以提供克隆包装,您可以在其中通过包含/排除列表来决定在深层复制期间选择哪些属性。 创建API时,这是相当普遍的做法。
你可以选择做一个浅复制ONLY_IF你了解所涉及的利害关系。 当你有一个指针的数量巨大,处理在C ++或C,做一个对象的浅拷贝确实是一个坏主意。
Example_OF_DEEP COPY_例如,当您尝试进行图像处理和对象识别时,您需要在处理区域之外遮盖“不重复运动”。 如果使用图像指针,则可能具有保存这些蒙版图像的规范。 现在...如果您进行图像的浅表复制,则当指针引用从堆栈中被杀死时,您将丢失该引用及其副本,即在某个时候会出现访问冲突的运行时错误。 在这种情况下,您需要克隆其图像的深层副本。 这样,您便可以在将来需要时取回这些口罩。
EXAMPLE_OF_SHALLOW_COPY与StackOverflow中的用户相比,我的知识面不是很广,所以可以删除此部分并举一个很好的例子。 但是我真的认为,如果您知道程序将无限期运行,即使用函数调用在堆栈上进行连续的“ push-pop”操作,则执行浅表复制不是一个好主意。 如果您要向业余或新手演示某些内容(例如C / C ++教程内容),那么可能就可以了。 但是,如果您正在运行监视和检测系统或Sonar跟踪系统之类的应用程序,则不应随便复制对象,因为它迟早会杀死您的程序。
#4楼
浅复制是创建一个新对象,然后将当前对象的非静态字段复制到新对象。 如果字段是值类型->将对该字段进行逐位复制; 对于引用类型 ->复制引用,但不复制引用的对象; 因此,原始对象及其克隆引用相同的对象。
深度复制将创建一个新对象,然后将当前对象的非静态字段复制到新对象。 如果字段是值类型 ->将对该字段进行逐位复制。 如果字段是引用类型 ->将执行引用对象的新副本。 要克隆的类必须标记为[Serializable]。
#5楼
简而言之,它取决于什么指向什么。 在浅表副本中,对象B指向对象A在内存中的位置。 在深层复制中,对象A的存储位置中的所有内容都将复制到对象B的存储位置。
这篇Wiki文章有一个很棒的图表。
http://en.wikipedia.org/wiki/Object_copy
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3145562