浅拷贝

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

拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这个内存空间的所有指针需要重新定义,不然会造成野指针错误。

简介浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

一般情况下,只需使用系统提供的浅拷贝构造函数即可,但是,如果对象的数据成员包括指向堆空间的指针,就不能使用这种拷贝方式,因为两个对象都拥有同一个资源,对象析构时,该资源将经历两次资源返还,此时必须自定义深拷贝构造函数,为创建的对象分配堆空间,否则会出现动态分配的指针变量悬空的情况1。

深拷贝与延迟拷贝深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

延迟拷贝是浅拷贝和深拷贝的一个组合,实际上很少会使用。 当最开始拷贝一个对象时,会使用速度较快的浅拷贝,还会使用一个计数器来记录有多少对象共享这个数据。当程序想要修改原始的对象时,它会决定数据是否被共享(通过检查计数器)并根据需要进行深拷贝。延迟拷贝从外面看起来就是深拷贝,但是只要有可能它就会利用浅拷贝的速度。当原始对象中的引用不经常改变的时候可以使用延迟拷贝。由于存在计数器,效率下降很高,但只是常量级的开销。而且, 在某些情况下, 循环引用会导致一些问题。

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

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

代码示例public class Subject { private String name; public Subject(String s) { name = s; } public String getName() { return name; } public void setName(String s) { name = s; } }public class Student implements Cloneable { // 对象引用 private Subject subj; private String name; public Student(String s, String sub) { name = s; subj = new Subject(sub); } public Subject getSubj() { return subj; } public String getName() { return name; } public void setName(String s) { name = s; } /** * 重写clone()方法 * @return */ public Object clone() { //浅拷贝 try { // 直接调用父类的clone()方法 return super.clone(); } catch (CloneNotSupportedException e) { return null; } } }本词条内容贡献者为:

王慧维 - 副研究员 - 西南大学

科技工作者之家

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