深拷贝

科技工作者之家 2020-11-17

一个引用对象一般来说由两个部分组成:一个具名的Handle,也就是我们所说的声明(如变量)和一个内部(不具名)的对象,也就是具名Handle的内部对象。它在Manged Heap(托管堆)中分配,一般由新增引用对象的New方法是进行创建。深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等。

简介如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,浅拷贝会带来数据安全方面的隐患。在进行赋值之前,为指针类型的数据成员另辟了一个独立的内存空间,实现真正内容上的拷贝1。这种拷贝称为深拷贝。深拷贝有两种方式实现:层层clone的方法和利用串行化来做深拷贝。层层clone的方法:在浅拷贝的基础上实现,给引用类型的属性添加克隆方法,并且在拷贝的时候也实现引用类型的拷贝。此种方法由于要在多个地方实现拷贝方法,可能会造成混论。利用串行化来做深拷贝:为避免复杂对象中使用clone方法可能带来的换乱,可以使用串化来实现深拷贝。先将对象写到流里,然后再重流里读出来。

构造函数在C+ +面向对象程序设计中,通过构造函数对对象进行初始化,它可以为对象在计算机内存中开辟内存空间,也可以为对象的数据成员提供初始值。构造函数是一个与类同名,没有返回值的特殊成员函数,每当创建一个对象时(包括使用new动态创建对象),编译系统就会自动调用构造函数。构造函数象类以外的一般函数和类成员函数一样可以重载和带缺省参数,构造函数的重载为对象的生成提供了各种灵活的手段。构造函数分为缺省构造函数(默认构造函数)和用户自定义构造函数。当程序员没有定义构造函数时,系统会提供一个无参的缺省构造函数。如果用户自定义了一个构造函数,编译器提供的缺省构造函数就自动消失了。

拷贝构造函数拷贝构造函数的功能是用一个已有的对象来初始化一个被创建的同类的对象,是一种特殊的构造函数,具有一般构造函数的所有特性,其形参是本类对象的引用。用户可以根据自己实际问题的需要定义特定的拷贝构造函数,以实现同类对象之间数据成员的传递。如果用户没有声明类的拷贝构造函数,系统就会自动生成一个缺省拷贝构造函数,这个缺省拷贝构造函数的功能是把初始对象的每个数据成员的值都复制到新建立的对象中。拷贝构造函数的声明形式为:类名(类名&对象名);下面定义了一个cat类和cat类的拷贝构造函数:

class cat{ private: int age; float weight; char* color; public: cat(); cat(cat&); void play(); void hunt();};cat::cat(cat&other){ age= other.age; weight= other.weight; color= other.color;}调用拷贝构造函数有以下三种情况:

(1)用类的一个对象去初始化另一个对象时。

cat cat1;

cat cat2(cat1); //创建cat2时系统自动调用拷贝构造函数,用cat1初始化cat2。

(2)对象作为函数参数传递时,调用拷贝构造函数。

f(cat a){} //定义f函数,形参为cat类对象cat b; //定义对象b

f(b);//进行f函数调用时,系统自动调用拷贝构造函数

(3)如果函数的返回值是类的对象,函数调用返回时,调用拷贝构造函数。

cat f() //定义f函数,函数的返回值为cat类的对象

{cat a; …return a;}cat b;//定义对象b

b= f();//调用f函数,系统自动调用拷贝构造函数

代码示例public static void main(String[] args) { TestClass aaa = new TestClass("yanjun", 23); aaa.getCat().setColor("red"); aaa.getCat().setSize(23); TestClass bbb = (TestClass) aaa.clone(); aaa.setName("new yanjun"); aaa.setAge(18); aaa.getCat().setColor("blue"); aaa.getCat().setSize(18); System.out.println(aaa.getName() + "--------" + bbb.getName()); //输出new yanjun--------yanjun System.out.println(aaa.getAge() + "--------" + bbb.getAge());//输出18--------23 System.out.println(aaa.getCat().getColor() + "--------" + bbb.getCat().getColor());//输出blue--------red System.out.println(aaa.getCat().getSize() + "--------" + bbb.getCat().getSize());//输出18--------23}class TestClass implements Cloneable{ private String name; private int age; private Cat cat; public TestClass(String name, int age){ this.name = name; this.age = age; this.cat = new Cat(); } //省去get和set方法 public Object clone(){ TestClass o=null; try{ o=(TestClass)super.clone();//Object 中的clone()识别出你要复制的是哪一个对象。 } catch(CloneNotSupportedException e){ System.out.println(e.toString()); } o.cat = (Cat)o.cat.clone(); return o; } }class Cat{ private String color; private int size; //省去get和set方法 public Cat() { this.color = "red"; this.size = 23; } public Object clone(){ Object o=null; try{ o=(Cat)super.clone();//Object 中的clone()识别出你要复制的是哪一个对象。 } catch(CloneNotSupportedException e){ System.out.println(e.toString()); } return o; } }本词条内容贡献者为:

李嘉骞 - 博士 - 同济大学

科技工作者之家

科技工作者之家APP是专注科技人才,知识分享与人才交流的服务平台。