深拷贝和浅拷贝有什么区别?

What is the difference between a deep copy and a shallow copy?

提问人:David Locke 提问时间:10/9/2008 最后编辑:Dariusz WoźniakDavid Locke 更新时间:11/10/2023 访问量:824291

问:

这个问题的答案是社区的努力。编辑现有答案以改进此帖子。它目前不接受新的答案或交互。

深拷贝和浅拷贝有什么区别?

与语言无关的 深拷 浅拷贝

评论


答:

180赞 helloandre 10/9/2008 #1

简而言之,这取决于什么指向什么。在浅拷贝中,对象 B 指向对象 A 在内存中的位置。在深层拷贝中,对象 A 的内存位置中的所有内容都会复制到对象 B 的内存位置。

维基百科文章对象副本有一个很棒的图表。

69赞 Martin York 10/9/2008 #2

浅拷贝:将成员值从一个对象复制到另一个对象。

深层复制:将成员值从一个对象复制到另一个对象。
任何指针对象都会被复制并深度复制。

例:

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.)
900赞 S.Lott 10/9/2008 #3

浅拷贝尽可能少地重复。集合的浅拷贝是集合结构的副本,而不是元素的副本。使用浅拷贝时,两个集合现在共享各个元素。

深度复制复制所有内容。集合的深层副本是两个集合,其中原始集合中的所有元素都已复制。

评论

0赞 Ilya Serbis 10/19/2012
可能是 .NET MemberwiseClone() 实现所做的不仅仅是传统意义上的浅层复制
11赞 cregox 1/10/2015
请记住,还有混合副本(不仅如此,例如懒惰副本),它只复制其中的一部分(这是一个实例)!;)
3赞 mfaani 4/12/2016
什么是集合结构?
1赞 Murphy 8/9/2016
@Honey 集合可以是存储多个数据项的多种数据结构。在python中,我们有元组,列表,字典等
7赞 Raphael Schmitz 2/21/2019
@RoyiNamir 在过去的 7 年里,您可能已经弄清楚了这一点,但对于其他任何想知道这一点的人来说:“浅拷贝一点一点地复制值类型”是正确的,但这有点令人困惑。如果有一个对象“具有”一个对象,则“逐位”复制该对象意味着复制指向该对象的指针/引用。原始和复制都指向同一个对象,而深层复制将创建一个新对象并指向该对象。CustomerAddressCustomerAddressAddressAddress
37赞 John Dibling 10/9/2008 #4
char * Source = "Hello, world.";

char * ShallowCopy = Source;    

char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);        

“ShallowCopy”指向内存中与“Source”相同的位置。 “DeepCopy”指向内存中的不同位置,但内容相同。

10赞 Dour High Arch 10/9/2008 #5
var source = { firstName="Jane", lastname="Jones" };
var shallow = ShallowCopyOf(source);
var deep = DeepCopyOf(source);
source.lastName = "Smith";
WriteLine(source.lastName); // prints Smith
WriteLine(shallow.lastName); // prints Smith
WriteLine(deep.lastName); // prints Jones

评论

0赞 CMircea 4/17/2010
这不是一个好例子。浅拷贝多用于快速复制对象,无需复制数据,但一旦对象需要修改共享数据,就会对其进行深拷贝。你的例子可能会让初学者感到困惑。
0赞 DragonLord 11/16/2014
这仅适用于使用指针表示字符串的语言。DHA 试图表达的观点是,浅拷贝只复制指向相同(单一)原始内容的指针,而深拷贝也会克隆指针的引用内容。这两种方法都复制表面内容。如果语言将字符串存储为表面文字内容,例如在 WAV 标头中,则此示例将不起作用。请注意,对于大多数不深奥的现实生活中的问题来说,这可能太挑剔了。
51赞 Bill K 10/9/2008 #6

我在这里没有看到一个简短、易于理解的答案——所以我会试一试。

使用浅拷贝时,源指向的任何对象也会由目标指向(因此不会复制任何引用的对象)。

使用深层拷贝时,源指向的任何对象都会被复制,而目标将指向副本(因此现在每个引用的对象将有 2 个)。这将在对象树中递归。

1038赞 dlamblin 10/9/2008 #7

广度与深度;从以对象为根节点的引用树的角度来考虑。

浅:

Before Copy Shallow Copying Shallow Done

变量 A 和 B 指的是不同的内存区域,当 B 分配给 A 时,这两个变量指的是同一个内存区域。以后对其中任何一个内容的修改会立即反映在另一个内容中,因为它们共享内容。

深:

Before Copy Deep Copying Deep Done

变量 A 和 B 指的是不同的内存区域,当 B 分配给 A 时,A 指向的内存区域中的值被复制到 B 指向的内存区域。后来对 A 或 B 内容的修改仍然是 A 或 B 独有的;内容不共享。

评论

44赞 corbin 11/7/2013
这是这个插图来自的维基百科文章,以防万一它对你来说没有意义 en.wikipedia.org/wiki/Object_copy#Shallow_copy
4赞 tek3 1/16/2015
在浅拷贝的情况下,如果我们在数组 B 中进行任何更改,这会反映在数组 A 中,因为 A 和 B 都指向相同的内存位置?
6赞 mannuscript 6/5/2017
在单行中,它通过引用复制与按值复制。不确定答案是否正确!
19赞 dlamblin 9/7/2017
@jasonleonhard 所以 9 年前,我只是将 url 放在图像上,因为不支持嵌入图像。因此,该 URL 引用了其来源。社区后来将 URL 制作成嵌入图像,而没有编辑某种引用。4 岁的热门评论也指出了您指出的内容。看一看: stackoverflow.com/posts/184780/revisions 为什么不自己将引文编辑成答案呢?下次有人对我 10 岁的写作风格有一些抱怨时,我可能无法联系。
8赞 Peter Guan 9/19/2018
“对于变量 A 和 B,当 B 分配给 A 时”,这难道不意味着代码中的“A = B”吗?我有点困惑,因为图像反映了“B = A”。
17赞 Jeffrey L Whitledge 10/9/2008 #8

在面向对象编程中,类型包括成员字段的集合。这些字段可以按值或引用(即指向值的指针)存储。

在浅拷贝中,将创建该类型的新实例,并将值复制到新实例中。引用指针也会像复制值一样被复制。因此,引用指向原始对象。对通过引用存储的成员所做的任何更改都会出现在原始对象和副本中,因为没有对引用的对象进行任何复制。

在深层复制中,将像以前一样复制按值存储的字段,但不会复制指向通过引用存储的对象的指针。而是对引用的对象进行深层复制,并存储指向新对象的指针。对这些引用的对象所做的任何更改都不会影响该对象的其他副本。

13赞 GovindaRaju 2/21/2011 #9

“ShallowCopy”指向内存中与“Source”相同的位置。“DeepCopy”指向内存中的不同位置,但内容相同。

评论

1赞 Bill K 4/6/2017
这有点误导。浅拷贝和深拷贝都会将对象复制到内存中的新位置,深拷贝也会复制子对象,而浅拷贝只会让新对象引用旧子对象。如果不参考原始对象,就很难阅读。
5赞 notytony 8/26/2011 #10
struct sample
{
    char * ptr;
}
void shallowcpy(sample & dest, sample & src)
{
    dest.ptr=src.ptr;
}
void deepcpy(sample & dest, sample & src)
{
    dest.ptr=malloc(strlen(src.ptr)+1);
    memcpy(dest.ptr,src.ptr);
}
7赞 santhosh 12/2/2011 #11

简单来说,浅拷贝类似于按引用调用,而深拷贝类似于按值调用

在引用调用中,函数的形式参数和实际参数都引用相同的内存位置和值。

在按值调用中,函数的形式参数和实际参数都引用了不同的内存位置,但具有相同的值。

1赞 komizo 12/20/2012 #12

复制 ararys :

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]);
    }

克隆意味着只复制克隆数组所表示的内存。

如果数组包含值类型对象,则复制这些值;

如果数组包含引用类型,则仅复制引用 - 因此有两个数组,其成员引用相同的对象

要创建深层拷贝(其中引用类型是重复的),必须遍历数组并手动克隆每个元素。

评论

0赞 DeanOC 12/20/2012
我不了解其他语言,但在 C#/VB 中,浅层复制值类型数组不会复制值。这两个数组引用相同的对象。向窗体添加按钮并添加以下代码以查看:private void button1_Click(object sender, EventArgs e) { int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{6,7,8,9,0}; MessageBox.Show(arr1[2] + " " + arr2[2]); arr2 = arr1; MessageBox.Show(arr1[2] + " " + arr2[2]); arr1[2] = 12; MessageBox.Show(arr1[2] + " " + arr2[2]); }
0赞 komizo 12/21/2012
你是对的,我更正了我的答案,更准确地说,在数组上使用克隆。您绝对正确,“浅层复制值类型的数组不会复制值”,但是在数组上使用克隆确实如此。我试着解释一下,试试吧。谢谢
72赞 Abhishek Bedi 1/23/2013 #13

特别是对于iOS开发人员:

如果是 的浅拷贝,那么对于原始数据,它就像,对于对象,它就像BAB = [A assign];B = [A retain];

B 和 A 指向相同的内存位置

如果是 的深层拷贝,那么它就像BAB = [A copy];

B 和 A 指向不同的内存位置

B 内存地址与 A 的相同

B 与 A 的内容相同

评论

9赞 10/26/2015
“B 内存地址与 A 相同” - 为什么会这样?
3赞 ismail baig 5/8/2018
在 Deep Copy 中,“B 内存地址与 A 的地址不同”
37赞 ha9u63a7 2/1/2013 #14

{想象两个对象:A 和 B 的类型相同 _t(相对于 C++),您正在考虑将 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我真的认为,如果你知道你的程序将无限期地运行,即使用函数调用在堆栈上连续的“push-pop”操作,那么做浅拷贝不是一个好主意。如果你正在向业余爱好者或新手演示一些东西(例如C / C++教程的东西),那么它可能没问题。但是,如果您正在运行监视和检测系统或声纳跟踪系统等应用程序,则不应该保持浅层复制对象,因为它迟早会杀死您的程序。

2赞 Rajaram Shelar 8/8/2013 #15

层复制是创建一个新对象,然后将当前对象的非静态字段复制到新对象中。如果字段是值类型 -->则执行该字段的逐位复制;对于引用类型 --> 引用被复制,但引用对象未被复制;因此,原始对象及其克隆引用同一对象。

深层复制是创建一个新对象,然后将当前对象的非静态字段复制到新对象。如果字段是值类型 -->则执行该字段的逐位复制。如果字段是引用类型 -->则执行引用对象的新副本。要克隆的类必须标记为 [Serializable]。

0赞 Avinash Goud N J 12/21/2013 #16

除了上述所有定义之外,还有一个最常用的深层复制,即在类的复制构造函数(或重载赋值操作器)中。

浅复制 --> 是指不提供复制构造函数。在这里,只复制对象,但不复制类的所有成员。

深层复制 --> 是指您决定在类中实现复制构造函数或重载赋值,并允许复制类的所有成员。

MyClass& MyClass(const MyClass& obj) // copy constructor for MyClass
{
          // write your code, to copy all the members and return the new object
}
MyClass& operator=(const MyClass& obj) // overloading assignment operator,
{
          // write your code, to copy all the members and return the new object
}
1赞 royal52 2/8/2014 #17

复制构造函数用于使用先前创建的同一类的对象初始化新对象。默认情况下,编译器编写的是一个浅拷贝。当不涉及动态内存分配时,浅拷贝工作正常,因为当涉及动态内存分配时,两个对象将指向堆中的同一内存位置,因此为了消除这个问题,我们编写了深拷贝,以便两个对象在内存中都有自己的属性副本。 为了阅读包含完整示例和解释的详细信息,您可以查看文章 C++ 构造函数

3赞 Santosh 3/7/2014 #18

摘自 [博客]:http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

深层复制涉及使用一个对象的内容创建同一类的另一个实例。在深层复制中,两个对象可能包含相同的信息,但目标对象将具有自己的缓冲区和资源。任何一个物体的破坏都不会影响剩余的物体。重载赋值运算符将创建对象的深层副本。

浅拷贝涉及将一个对象的内容复制到同一类的另一个实例中,从而创建镜像。由于引用和指针的直接复制,这两个对象将共享另一个对象的相同外部包含的内容,因此是不可预测的。

解释:

使用复制构造函数,我们只需逐个成员复制数据值。这种复制方法称为浅拷贝。如果对象是一个简单的类,由内置类型组成,没有指针,这是可以接受的。此函数将使用值和对象,并且其行为不会通过浅拷贝更改,仅复制作为成员的指针的地址,而不是地址指向的值。然后,该函数会无意中更改对象的数据值。当函数超出范围时,对象及其所有数据的副本将从堆栈中弹出。

如果对象有任何指针,则需要执行深层复制。使用对象的深层拷贝时,将为自由存储中的对象分配内存,并复制指向的元素。深层复制用于从函数返回的对象。

60赞 Touchstone 3/19/2014 #19

为了便于理解,您可以按照以下文章进行操作: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm


浅拷贝:

Shallow Copy


深层复制:

Deep Copy

17赞 Sunil Kumar Sahoo 9/16/2014 #20

深拷贝

深层拷贝复制所有字段,并复制字段指向的动态分配的内存。当一个对象与它所引用的对象一起被复制时,就会发生深层复制。

浅拷贝

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

评论

0赞 PhilPhil 4/5/2019
可悲的是,该链接不再有效 - 它现在指向 2019 年 2 月的一篇关于网页设计的文章(除非作者是千里眼?
37赞 atish shimpi 12/18/2014 #21

什么是浅文复制?

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

在此图中,具有 int 类型和 类型的字段。当您执行 的浅拷贝时,将创建包含复制的值 的 并且仍然指向自身。请注意,由于是原始类型,因此其值将复制到 but since 是一个对象,因此仍指向 。因此,对 in 所做的任何更改都将反映在 中。MainObject1field1ContainObject1ContainObjectMainObject1MainObject2field2field1ContainObject1field1field2ContainedObject1MainObject2ContainObject1ContainObject1MainObject1MainObject2

现在,如果这是浅拷贝,让我们看看什么是深拷贝?

什么是深度复制?

深层拷贝复制所有字段,并复制字段指向的动态分配的内存。当一个对象与它所引用的对象一起被复制时,就会发生深层复制。Deep Copy

在此图中,MainObject1 具有 int 类型和 类型的字段。当您执行 的深层复制时,将创建包含 的复制值和包含 的复制值。请注意,对 中所做的任何更改都不会反映在 中。field1ContainObject1ContainObjectMainObject1MainObject2field2field1ContainObject2ContainObject1ContainObject1MainObject1MainObject2

好文章

评论

0赞 Robb_2015 12/29/2015
这不是你的错,尽管这个例子指的是当能够尝试和理解与该问题一样深刻的东西时,该示例中的#3发生在哪里?field3ContainObject2
10赞 user4768611 5/7/2015 #22

浅拷贝 - 原始对象和浅拷贝对象中的引用变量具有对公共对象的引用。

深度复制 - 原始对象和深度复制对象中的引用变量引用不同的对象。

克隆总是做浅拷贝。

public class Language implements Cloneable{
    
    String name;
    public Language(String name){
        this.name=name;
    }
    
    public String getName() {
        return name;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

主类如下-

public static void main(String args[]) throws ClassNotFoundException, CloneNotSupportedException{

      ArrayList<Language> list=new ArrayList<Language>();
      list.add(new Language("C"));
      list.add(new Language("JAVA"));

      ArrayList<Language> shallow=(ArrayList<Language>) list.clone();
      //We used here clone since this always shallow copied.

      System.out.println(list==shallow);
      
      for(int i=0;i<list.size();i++)
      System.out.println(list.get(i)==shallow.get(i));//true
      
      ArrayList<Language> deep=new ArrayList<Language>();
      for(Language language:list){
          deep.add((Language) language.clone());
      }
      System.out.println(list==deep);
      for(int i=0;i<list.size();i++)
          System.out.println(list.get(i)==deep.get(i));//false
      
} 

上述输出将是-

假 真 真

假 假

原始物体所做的任何变化都会反映在浅层物体上,而不是深层物体中。

  list.get(0).name="ViSuaLBaSiC";
  System.out.println(shallow.get(0).getName()+"  "+deep.get(0).getName());

输出-ViSuaLBaSiC C

8赞 PeerNet 5/29/2015 #23

想象一下,有两个数组,分别称为 arr1 和 arr2。

arr1 = arr2;   //shallow copy
arr1 = arr2.clone(); //deep copy
223赞 Alexandr 6/15/2016 #24

尝试考虑下图

enter image description here

例如,Object.MemberwiseClone 创建一个浅拷贝链接

使用 ICloneable 接口,您可以获得深层拷贝,如此处所述

评论

63赞 Levi Fuller 6/26/2016
一张图片胜过千言万语。
17赞 Karan Singh 6/16/2017
哦,天哪,来这里是为了找出其中的意思。这是唯一有帮助的答案。
4赞 hina10531 3/19/2018
这是最简单的,但只显示了必要的内容。
2赞 chetan 6/11/2020
此答案解释了按引用复制与按值复制。浅拷贝与深拷贝是一个适用于集合的概念。看到这个答案和这个答案
0赞 nardnob 12/6/2020
这个概念不仅适用于集合
4赞 S2S2 9/30/2016 #25

要向其他答案添加更多内容,

  • 对象的浅拷贝对值类型执行按值复制 基于属性,对于基于引用类型的属性,按引用复制。
  • 对象的深层复制基于以下值类型按值执行复制 属性,以及基于引用类型的按值复制 层次结构深处的属性(引用类型)
1赞 Lance Ruo Zhang 1/12/2017 #26

为了混淆浅拷贝和简单地将新的变量名称分配给列表,再添加一点。

“假设我们有:

x = [
    [1,2,3],
    [4,5,6],
    ]

此语句创建 3 个列表:2 个内部列表和 1 个外部列表。然后,在名称 x 下提供对外部列表的引用。如果我们这样做

y = x

不会复制任何数据。我们在某处的记忆中仍然有相同的 3 个列表。所做的只是使外部列表除了其以前的名称 x 之外,还以名称 y 提供。如果我们这样做

y = list(x)

y = x[:]

这将创建一个内容与 x 相同的新列表。列表 x 包含对 2 个内部列表的引用,因此新列表也将包含对这 2 个内部列表的引用。只复制一个列表,即外部列表。 现在内存中有 4 个列表,两个内部列表,外部列表和外部列表的副本。原始外部列表以名称 x 提供,新的外部列表以名称 y 提供。

内部列表尚未复制!此时,您可以从 x 或 y 访问和编辑内部列表!

如果你有一个二维(或更高)的列表,或任何类型的嵌套数据结构,并且你想对所有内容进行完整复制,那么你需要在复制模块中使用deepcopy()函数。您的解决方案也适用于二维列表,因为遍历外部列表中的项目并创建每个项目的副本,然后为所有内部副本构建一个新的外部列表。

来源: https://www.reddit.com/r/learnpython/comments/1afldr/why_is_copying_a_list_so_damn_difficult_in_python/

4赞 Lova Chittumuri 3/6/2017 #27

浅拷贝不会创建新引用,但深层复制将创建新引用。

这是解释深文案和浅文案的程序。

public class DeepAndShollowCopy {
    int id;
    String name;
    List<String> testlist = new ArrayList<>();

    /*
    // To performing Shallow Copy 
    // Note: Here we are not creating any references. 
      public DeepAndShollowCopy(int id, String name, List<String>testlist)
       { 

       System.out.println("Shallow Copy for Object initialization");
       this.id = id; 
       this.name = name; 
       this.testlist = testlist; 

       }
    */  

    // To performing Deep Copy 
    // Note: Here we are creating one references( Al arraylist object ). 
    public DeepAndShollowCopy(int id, String name, List<String> testlist) {
        System.out.println("Deep Copy for Object initialization");
        this.id = id;
        this.name = name;
        String item;
        List<String> Al = new ArrayList<>();
        Iterator<String> itr = testlist.iterator();
        while (itr.hasNext()) {
            item = itr.next();
            Al.add(item);
        }
        this.testlist = Al;
    }


    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Oracle");
        list.add("C++");
        DeepAndShollowCopy copy=new DeepAndShollowCopy(10,"Testing", list);
        System.out.println(copy.toString());
    }
    @Override
    public String toString() {
        return "DeepAndShollowCopy [id=" + id + ", name=" + name + ", testlist=" + testlist + "]";
    }
}
12赞 Arun Raaj 9/26/2017 #28

层克隆:
定义:“对象的浅层副本复制了'主'对象,但不复制内部对象。 当自定义对象(例如。Employee)只有原始的字符串类型变量,然后使用浅克隆。

Employee e = new Employee(2, "john cena");
Employee e2=e.clone();

您返回被覆盖的 clone() 方法,您的作业就结束了。super.clone();

深度克隆
定义:“与浅层拷贝不同,深度拷贝是对象的完全独立副本。
表示当一个 Employee 对象包含另一个自定义对象时:

Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");

然后,您必须编写代码以在覆盖的 clone() 方法中克隆“Address”对象。否则,Address 对象不会克隆,并且在克隆的 Employee 对象中更改 Address 的值时会导致 bug,该值也反映了原始对象。

8赞 Sushant 1/20/2018 #29

浅拷贝构造一个新的复合对象,并将其引用插入到原始对象中。

与浅拷贝不同,深度复制构造新的复合对象,并插入原始复合对象的原始对象的副本。

让我们举个例子。

import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)

上面的代码打印 FALSE。

让我们看看如何。

原始复合对象(称为复合对象,因为它在对象中有对象 (Inception))x=[1,[2]]

enter image description here

如图所示,列表中有一个列表。

然后我们使用 创建一个浅拷贝。python在这里所做的是,它将创建一个新的复合对象,但其中的对象指向原始对象。y = copy.copy(x)

enter image description here

在图像中,它为外部列表创建了一个新副本。但内部列表与原始列表相同。

现在我们使用 创建它的 deepcopy。Python 在这里所做的是,它将为外部列表和内部列表创建新对象。如下图所示(红色突出显示)。z = copy.deepcopy(x)

enter image description here

最后代码打印,因为 y 和 z 不是同一个对象。False

15赞 Vivek Mehta 1/24/2018 #30

我想举个例子,而不是正式的定义。

var originalObject = { 
    a : 1, 
    b : 2, 
    c : 3,
};

此代码显示一个浅拷贝

var copyObject1 = originalObject;

console.log(copyObject1.a);         // it will print 1 
console.log(originalObject.a);       // it will also print 1 
copyObject1.a = 4; 
console.log(copyObject1.a);           //now it will print 4 
console.log(originalObject.a);       // now it will also print 4

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // now it will print 1

此代码显示一个深层副本

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // !! now it will print 1 !!

评论

0赞 Suresh Prajapati 8/12/2019
我得到1 1 4 4 4 4 4 4
0赞 Vivek Mehta 8/12/2019
在深层复制中,执行 copyObject.a = 8,然后检查。希望你能得到正确的答案。
0赞 Swarup Chavan 7/29/2020
object.assign({},arr) 不会创建深层副本,假设我们有以下对象 var source = {“foo”:1,“name”:“Testing”,c:{age:34}} var dCopy = Object.assign({},source) console.log(dCopy.c.age) console.log() source.c.age = 3 console.log(dCopy.c.age) console.log(Source deep ${source.c.age}Source deep ${source.c.age})
3赞 Nayas Subramanian 7/28/2018 #31

我从以下几行中理解了。

浅拷贝将对象值类型(int、float、bool)字段复制到目标对象,对象的引用类型(字符串、类等)被复制为目标对象中的引用。在此目标中,引用类型将指向源对象的内存位置。

深层复制将对象的值和引用类型复制到目标对象的全新副本中。这意味着值类型和引用类型都将被分配一个新的内存位置。