详解常见面试题---深拷贝和浅拷贝(C++)
大家好,我是KookNut39,在CSDN写文,分享一些自己认为在学习过程中比较重要的东西,致力于帮助初学者入门,希望可以帮助你进步。最近在更新C/C++方面的知识,感兴趣的欢迎关注博主,可以去专栏查看之前的文章,希望未来能和大家共同探讨技术。
C++类对象的赋值操作分为深拷贝和浅拷贝两种,我们所说的的浅拷贝就是赋值操作,这种拷贝比较常见,比如:
class A
{public:A();~A();public:int i;
};A::A()
{i = 5;
}A::~A()
{}void main()
{A a1;//执行默认构造函数 初始化a1.i = 7A a2 = a1;//发生赋值操作 此刻a2.i = 5a2.i = 7;//只修改a2中的成员,对a1中的不造成影响return;
}
这就是一个简单的浅拷贝,当我们拷贝之后,发现变量 i 的值确实被拷贝过来了,此时a1和a2中的变量值都一样。
而我们对a2中的 i 进行操作,修改其中的内容的时候,并不影响a1中 i 的值。
但是如果我们的类中涉及到动态内存的申请与释放,那么简单的浅拷贝就会出现问题:
class A
{public:A();~A();public:char* ptr1;
};A::A()
{ptr1 = new char[5];memset(ptr1, 'h', 5);
}A::~A()
{if (ptr1 != nullptr){delete[]ptr1;ptr1 = nullptr;}}void main()
{A a1;//执行默认构造函数A a2 = a1;//发生赋值操作return;}
涉及到动态内存的分配与释放的时侯就比较危险,可能会造成对内存的二次释放,出现内存堆被破坏,导致内存奔溃的情况发生!这是为什么呢?我们上述代码中,对于类对象的赋值是简单的拷贝操作,也就是直接把a1中申请的那块内存的值复制给了a2中的ptr1对象,它相当于做了这样一个操作:
a2.ptr1 = a1.ptr1;
我们也可以通过调试信息来验证我们的这个说法:
我们可以从图中看到两个指针指向的地址是同一个地址,所以这只是指针的简单赋值,并没有开辟新的内存空间,那么我们都知道,当类的对象销毁的时候,类的析构函数会被执行,这样我们就会执行析构函数中的内存释放操作,我们目前在main函数中有两个对象a1和a2,那么肯定会分别执行各自的析构函数。那么就会对同一块内存区域释放两次,肯定会导致堆的奔溃,自然就导致内存奔溃!我们可以从动图中看到,第一次释放内存没问题!第二次释放内存导致内存奔溃!
但是我们可以用深拷贝来解决这个问题!
class A
{public:A();//默认构造函数A(const A& A1);//拷贝构造函数~A();public:char* ptr1;
};A::A()
{ptr1 = new char[5];memset(ptr1, 'h', 5);
}A::A(const A &A1)
{ptr1 = new char[5];strcpy(ptr1, A1.ptr1);
}A::~A()
{if (ptr1 != nullptr){delete[]ptr1;ptr1 = nullptr;}
}void main()
{A a1;//执行默认构造函数 A a2 = a1;//发生深拷贝赋值操作,另外开辟了内存空间A a3(a1);//发生深拷贝赋值操作,另外开辟了内存空间return;
}
在类中定义一个拷贝构造函数,传参传入当前类的引用,然后对内存进行重新的申请,再将指针指向内存中的内容进行复制操作,这样我们就完成了深拷贝,在内存析构时候自然就不会出现二次释放同一片内存的问题,我们可以从如下的调试截图中看到三个ptr1指针指向了不同的三个地址空间!
最后来看一下最终析构时候的调试动图,没有发生任何的内存奔溃。
码字不易,如果喜欢,赏个点赞+评论+收藏
详解常见面试题---深拷贝和浅拷贝(C++)相关推荐
- Python常见面试题:TCP 协议中的三次握手与四次挥手相关概念详解
今天来聊聊Python常见面试题中面试频率特别高的一个题目:TCP 协议中的三次握手与四次挥手. 涉及到的知识点有: 1.TCP.UDP 协议的区别 2.TCP 头部结构 3.三次握手与四次挥手过程详 ...
- Java开发常见面试题详解(LockSupport,AQS,Spring循环依赖,Redis)_3
Java开发常见面试题详解(LockSupport,AQS,Spring循环依赖,Redis)_3 总览 问题 详解 String.intern()的作用 link LeetCode的Two Sum题 ...
- Java开发常见面试题详解(JVM)_2
Java开发常见面试题详解(JVM)_2 JVM 问题 详解 JVM垃圾回收的时候如何确定垃圾?是否知道什么是GC Roots link 你说你做过JVM调优和参数配置,请问如何盘点查看JVM系统默认 ...
- HTTP协议与HTTPS协议详解(含常见面试题)
目录 1.HTTP协议 1.1HTTP协议是什么 1.2 HTTP协议工作过程 1.3 HTTP请求方法 1.4.HTTP请求报文和应答报文 1.5 HTTP状态码 2.HTTPS协议 2.1.什么是 ...
- JSP, Servlet常见面试题详解
JSP, Servlet常见面试题 1,J2EE是什么? J2EE本身是一个标准,一个为企业分布式应用的开发提供的标准平台. J2EE也是一个框架,包括JDBC.JNDI.RMI.JMS.EJB.JT ...
- web前端常见面试题
Vue面试题 生命周期函数面试题 1.什么是 vue 生命周期 2.vue生命周期的作用是什么 3.第一次页面加载会触发哪几个钩子 4.简述每个周期具体适合哪些场景 5.created和mounted ...
- javaspring框架教程,netty常见面试题
前言 现在刷抖音经常可以看到一些老外街坊,问他们最想把什么带回自己的国家,我听过很多的回答都是:淘宝,支付宝,美食,微信,外卖,高铁等等. 确实如此,随着国家的快速发展吸引了不少国际上羡慕的目光,更让 ...
- 2020最新Java面试题(java,JavaWeb,数据库,框架),常见面试题及答案汇总
1.面试题模块汇总 面试题包括以下十九个模块:Java 基础.容器.多线程.反射.对象拷贝.Java Web 模块.异常.网络.设计模式.Spring/Spring MVC.Spring Boot/S ...
- Android知识点汇总以及常见面试题
Android知识点汇总以及常见面试题 1. 链表和数组的区别 2. List Hash 数组的区别 3. 用过哪些三方SDK 4. Android四大组件 5. 堆和栈的区别 6. Activity ...
最新文章
- ubuntu 下 Could not get lock /var/lib/dpkg/lock解决方案
- 关于跨域请求的二三事
- 发布Akka Toolkit 2.3
- 笔记本屏幕30hz_你真的了解笔记本电池和电源适配器吗?
- php app()路由,谷歌云应用引擎app.yaml php72与路由问题
- 为什么选择红黑树作为底层实现
- baacloud无法连接到_加入 Beta 版“Baacloud88” - TestFlight - Apple
- 帝国cms会员注册页跳过选择注册会员类型
- 利用Css3样式属性Cursor来更换自定义个性化鼠标指针(光标)
- 敏捷开发Scrum学习
- 披荆斩棘,蜕变从来学吧这里开始
- matlab 层次聚类不均等巨雷,matlab层次聚类
- 文件损坏如何修复?简单的方法
- 大批量其他经纬度转换为百度地图经纬度
- mysql in个数限制_mysql where in 条件中参数个数问题
- 勾股定理算斜边用计算机怎么按,勾股定理怎么算斜边
- 前端可视化数据大屏(1)
- 经过半年的摸爬滚打,入门机器学习如此简单
- 2022-2028全球硬胶囊行业调研及趋势分析报告
- NC文件笔记(2020-09-14)
热门文章
- Java中自定义注解的使用
- 我想了一晚上的一道题目:关于dfs+回溯+部分图论
- 刘军旗书编《满江红》
- 第五人格显示服务器维护中请稍后登录怎么办,第五人格登录不上怎么办 登录不上解决方案...
- 百度最新股权结构曝光:李彦宏持股16.1% 第二大股东持股降至5.2%
- 微信小程序趋势及前景,大厂直通车!
- T-SQL Tips: 存储过程示例(典范)
- Spring Boot 线上项目管理
- 如何怎么样讲图片调成半透明效果#ps教程#ps学习#ps抠图
- 2020考研第一步:基本信息须知