大家好,我是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++)相关推荐

  1. Python常见面试题:TCP 协议中的三次握手与四次挥手相关概念详解

    今天来聊聊Python常见面试题中面试频率特别高的一个题目:TCP 协议中的三次握手与四次挥手. 涉及到的知识点有: 1.TCP.UDP 协议的区别 2.TCP 头部结构 3.三次握手与四次挥手过程详 ...

  2. Java开发常见面试题详解(LockSupport,AQS,Spring循环依赖,Redis)_3

    Java开发常见面试题详解(LockSupport,AQS,Spring循环依赖,Redis)_3 总览 问题 详解 String.intern()的作用 link LeetCode的Two Sum题 ...

  3. Java开发常见面试题详解(JVM)_2

    Java开发常见面试题详解(JVM)_2 JVM 问题 详解 JVM垃圾回收的时候如何确定垃圾?是否知道什么是GC Roots link 你说你做过JVM调优和参数配置,请问如何盘点查看JVM系统默认 ...

  4. HTTP协议与HTTPS协议详解(含常见面试题)

    目录 1.HTTP协议 1.1HTTP协议是什么 1.2 HTTP协议工作过程 1.3 HTTP请求方法 1.4.HTTP请求报文和应答报文 1.5 HTTP状态码 2.HTTPS协议 2.1.什么是 ...

  5. JSP, Servlet常见面试题详解

    JSP, Servlet常见面试题 1,J2EE是什么? J2EE本身是一个标准,一个为企业分布式应用的开发提供的标准平台. J2EE也是一个框架,包括JDBC.JNDI.RMI.JMS.EJB.JT ...

  6. web前端常见面试题

    Vue面试题 生命周期函数面试题 1.什么是 vue 生命周期 2.vue生命周期的作用是什么 3.第一次页面加载会触发哪几个钩子 4.简述每个周期具体适合哪些场景 5.created和mounted ...

  7. javaspring框架教程,netty常见面试题

    前言 现在刷抖音经常可以看到一些老外街坊,问他们最想把什么带回自己的国家,我听过很多的回答都是:淘宝,支付宝,美食,微信,外卖,高铁等等. 确实如此,随着国家的快速发展吸引了不少国际上羡慕的目光,更让 ...

  8. 2020最新Java面试题(java,JavaWeb,数据库,框架),常见面试题及答案汇总

    1.面试题模块汇总 面试题包括以下十九个模块:Java 基础.容器.多线程.反射.对象拷贝.Java Web 模块.异常.网络.设计模式.Spring/Spring MVC.Spring Boot/S ...

  9. Android知识点汇总以及常见面试题

    Android知识点汇总以及常见面试题 1. 链表和数组的区别 2. List Hash 数组的区别 3. 用过哪些三方SDK 4. Android四大组件 5. 堆和栈的区别 6. Activity ...

最新文章

  1. ubuntu 下 Could not get lock /var/lib/dpkg/lock解决方案
  2. 关于跨域请求的二三事
  3. 发布Akka Toolkit 2.3
  4. 笔记本屏幕30hz_你真的了解笔记本电池和电源适配器吗?
  5. php app()路由,谷歌云应用引擎app.yaml php72与路由问题
  6. 为什么选择红黑树作为底层实现
  7. baacloud无法连接到_加入 Beta 版“Baacloud88” - TestFlight - Apple
  8. 帝国cms会员注册页跳过选择注册会员类型
  9. 利用Css3样式属性Cursor来更换自定义个性化鼠标指针(光标)
  10. 敏捷开发Scrum学习
  11. 披荆斩棘,蜕变从来学吧这里开始
  12. matlab 层次聚类不均等巨雷,matlab层次聚类
  13. 文件损坏如何修复?简单的方法
  14. 大批量其他经纬度转换为百度地图经纬度
  15. mysql in个数限制_mysql where in 条件中参数个数问题
  16. 勾股定理算斜边用计算机怎么按,勾股定理怎么算斜边
  17. 前端可视化数据大屏(1)
  18. 经过半年的摸爬滚打,入门机器学习如此简单
  19. 2022-2028全球硬胶囊行业调研及趋势分析报告
  20. NC文件笔记(2020-09-14)

热门文章

  1. Java中自定义注解的使用
  2. 我想了一晚上的一道题目:关于dfs+回溯+部分图论
  3. 刘军旗书编《满江红》
  4. 第五人格显示服务器维护中请稍后登录怎么办,第五人格登录不上怎么办 登录不上解决方案...
  5. 百度最新股权结构曝光:李彦宏持股16.1% 第二大股东持股降至5.2%
  6. 微信小程序趋势及前景,大厂直通车!
  7. T-SQL Tips: 存储过程示例(典范)
  8. Spring Boot 线上项目管理
  9. 如何怎么样讲图片调成半透明效果#ps教程#ps学习#ps抠图
  10. 2020考研第一步:基本信息须知