c++深拷贝和浅拷贝[通俗易懂]

c++深拷贝和浅拷贝[通俗易懂]C++中类的拷贝有两种:深拷贝,浅拷贝当出现类的等号赋值时,会调用拷贝函数在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。所以,这时,必须采用深拷贝。深拷贝与浅拷贝

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

C++中类的拷贝有两种:深拷贝,浅拷贝:当出现类的等号赋值时,即会调用拷贝函数
一:两个的区别
1  在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的;但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象,所以,此时,必须采用深拷贝。
2 深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。简而言之,当数据成员中有指针时,必须要用深拷贝。
二  带实例的解释
c++默认的拷贝构造函数是浅拷贝
浅拷贝就是对象的数据成员之间的简单赋值,如你设计了一个没有类而没有提供它的复制构造函数,当用该类的一个对象去给令一个对象赋值时所执行的过程就是浅拷贝,如:
class A 
{ 
	public: 
	A(int _data) : data(_data){} 
	A(){}
	private: 
	int data;
 };
int main() 
{ 
	A a(5), b = a; // 仅仅是数据成员之间的赋值 
}
这一句b = a;就是浅拷贝,执行完这句后b.data = 5;
如果对象中没有其他的资源(如:堆,文件,系统资源等),则深拷贝和浅拷贝没有什么区别,
但当对象中有这些资源时,例子:
class A 
{ 
	public: 
	A(int _size) : size(_size)
	{
		data = new int[size];
	} // 假如其中有一段动态分配的内存 
	A(){};
	 ~A()
	{
		delete [] data;
	} // 析构时释放资源
	private: 
	int* data;
	int size; 
}
int main() 
{ 
	A a(5), b = a; // 注意这一句 
}
这里的b = a会造成未定义行为,因为类A中的复制构造函数是编译器生成的,所以b = a执行的是一个浅拷贝过程。我说过浅拷贝是对象数据之间的简单赋值,比如:
b.size = a.size;
b.data = a.data; // Oops!
这里b的指针data和a的指针指向了堆上的同一块内存,a和b析构时,b先把其data指向的动态分配的内存释放了一次,而后a析构时又将这块已经被释放过的内存再释放一次。对同一块动态内存执行2次以上释放的结果是未定义的,所以这将导致内存泄露或程序崩溃所以这里就需要深拷贝来解决这个问题,深拷贝指的就是当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用)时,对象的另开辟一块新的资源,而不再对拷贝对象中有对其他资源的引用的指针或引用进行单纯的赋值。如:
class A 
{ 
	public: 
	A(int _size) : size(_size)
	{
		data = new int[size];
	} // 假如其中有一段动态分配的内存 
	A(){};
	A(const A& _A) : size(_A.size)
	{
		data = new int[size];
	} // 深拷贝 
	~A()
	{
		delete [] data;
	} // 析构时释放资源
	private: 
	int* data; 
 	int size;
 }
int main() 
{ 
	A a(5), b = a; // 这次就没问题了 
}
总结:深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/187091.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • centos7配置虚拟ip_centos临时设置ip

    centos7配置虚拟ip_centos临时设置ip环境概览master:192.168.46.26slave1:192.168.46.27测试机:192.168.46.22(用于ping机器)安装keepalivedyuminstall-ykeepalived修改masterkeepalived.conf配置文件vim/etc/keepalived/keepalived.confinterface修改为自己的网卡(使用ipaddr查看)priority修改其参数为188设置为主节点virtual_ipadd

    2022年10月11日
    3
  • 集合遍历

    集合遍历

    2021年8月31日
    46
  • webpack基础打包命令_webpack打包原理

    webpack基础打包命令_webpack打包原理没有配置文件的打包如果我们没有使用配置文件webpack.config.js,那么我们就需要通过命令来打包案例我们首先创建一个webpackTest文件夹,然后在文件夹中再创建2个子文件夹dis

    2022年7月31日
    5
  • EVE模拟器教程之如何设置预配[通俗易懂]

    EVE模拟器教程之如何设置预配[通俗易懂]很多时候我们想把EVE所有的配置都清空,但是又想在清空时保存最基本的预配,比如IP地址,Hostname等等,以下为设置预配详细步骤:1)配置好每台设备的IP地址,计算机名,以及你想预配的信息,然后保存。2)选择菜单选项栏Moreactions—ExportallCFGs注意右边消息窗口弹出configexported并且无错误,此导出步骤请重复2-3遍。…

    2022年6月10日
    37
  • mysql list table_java resultset转list

    mysql list table_java resultset转list我在Orcle里写了一个Sql语句,用到了LISTAGG,现在要改成mysql数据库,我要怎么改这个Sql语句?SELECTA.GUID,A.COMPANY_GUID,A.GOODS_CODE,A.GOODS_NAME,A.SPECIFICATIONS,A.SMALL_IM…我在Orcle里写了一个Sql语句,用到了LISTAGG,现在要改成mysql数据库,我要怎么改这个Sql语句?SELE…

    2022年9月6日
    7
  • html文本框鼠标离开事件,html鼠标事件_文本框事件「建议收藏」

    html文本框鼠标离开事件,html鼠标事件_文本框事件「建议收藏」该楼层疑似违规已被系统折叠隐藏此楼查看此楼今天57号网络技术分享给大家介绍html鼠标事件,就是当前文本框获得焦点时,里面的原有文本清零。首先我们来看一看源代码运行后的效果图片:你也可以【点击预览】,看到我们真实的效果。下面是源代码,喜欢就支持一下吧:/p>Transitional//EN””http://www.w3.org/TR/xhtml1/DTD/xhtml1-transition…

    2025年8月8日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号