深度复制和浅复制的区别是什么?


当前回答

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

这篇wiki文章有一个很好的图表。

http://en.wikipedia.org/wiki/Object_copy

其他回答

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

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

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

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

为了便于理解,你可以参考这篇文章: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm


浅拷贝:


深拷贝:

浅复制-原始和浅复制对象中的引用变量引用公共对象。

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

克隆总是做浅拷贝。

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