深拷贝和浅拷贝有什么区别?
char * Source = "Hello, world.";
char * ShallowCopy = Source;
char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);
'ShallowCopy'指向内存中与'Source'相同的位置。 'DeepCopy'指向内存中不同的位置,但其内容相同。
深拷贝
深拷贝会拷贝所有字段,并复制指向这些字段的动态分配的内存。当一个对象被复制时,如果它引用了其他对象,则也会将其引用的对象一起复制。
浅拷贝
浅拷贝是对一个对象进行逐位拷贝的操作。创建一个新对象,在原始对象中的所有值都得到了精确拷贝。如果对象中的任何字段都是对其他对象的引用,则只会拷贝引用地址,即仅拷贝内存地址。
我想举一个例子而不是给出正式定义。
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 !!
1 1 4 4 4 4 4 4
。 - Suresh PrajapatiSource deep ${source.c.age}
)source.c.age = 3console.log(dCopy.c.age)
console.log(Source deep ${source.c.age}
) - Swarup Chavan'ShallowCopy'指向和'Source'相同的内存位置。'DeepCopy'指向不同的内存位置,但内容相同。
浅拷贝:
定义:“对象的浅拷贝复制了‘主’对象,但不会复制内部对象。”当自定义对象(例如: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'对象。否则,地址对象将不会被克隆,并且当您更改克隆的Employee对象中的地址值时,它会影响原始对象。
浅拷贝- 原始对象和浅拷贝对象中的引用变量都指向同一个对象。
深拷贝- 原始对象和深拷贝对象中的引用变量指向不同的对象。
克隆操作总是进行浅拷贝。
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());
输出 - Visual Basic C
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
arr1 = arr2; //shallow copy
arr1 = arr2.clone(); //deep copy
浅拷贝会构建一个新的复合对象,并将其引用插入到原始对象中。
与浅拷贝不同,深拷贝会构建新的复合对象,并且还会插入原始复合对象中原始对象的副本。
让我们来看一个例子。
import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)
正如您在图像中所看到的那样,其中有一个列表内嵌在另一个列表中。
然后我们使用y = copy.copy(x)
创建它的浅拷贝。Python 在此处所做的是创建一个新的复合对象,但其中的对象指向原始对象。
z = copy.deepcopy(x)
创建它的深层副本。Python在这里所做的是,它将为外部列表和内部列表创建新对象。如下图所示(红色突出显示)。
代码结束时打印 False
,因为 y 和 z 不是同一个对象。
希望对你有所帮助。