大二学生血泪教训:C++深浅拷贝详解 面试必问

作为C++初学者,当你开始使用指针和动态内存分配时,“深拷贝”和“浅拷贝”是必须跨越的一道坎。不理解它们,轻则程序崩溃,重则内存泄漏。让我带你彻底搞懂这两个概念的区别、应用场景以及如何正确实现它们。

概述

浅拷贝因为初始化或者赋值一个对象时,会把指针也复制过去从而导致析构函数重复delete,导致世界末日

通过深拷贝用不同的内存空间,这样就不会重复delete掉两次了

一、什么是拷贝

在C++中,对象拷贝主要发生在两种场景:

1.使用一个对象初始化另一个对象,说人话就是新建一个对象等于另一个对象

Myclass obj2 = obj1 (这里调用了拷贝构造函数)

2.将一个对象赋值给另一个已存在的对象,也就是令一个对象和另一个对象相等

obj2 = obj1 (这里调用了赋值运算符 operator= )

默认情况下,编译器会自动生成拷贝构造函数和赋值运算符。

它们逐个成员地复制对象的内容。对于基本数据类型(int, float, char等),这种复制是直接的值拷贝,这一部分是没有问题的。问题就出在当我们的类成员包含指针,并且这些指针指向动态分配的内存(堆内存)时。

二、浅拷贝潜伏危机

浅拷贝只复制对象中的内存地址,而不复制这个指针所指的那块内存。结果是,拷贝后的对象和原对象的指针成员指向同一块堆内存

刚才我们提到的默认情况下, 就是编译器的浅拷贝。

我们来看一下运行结果:

构造函数调用: 分配内存 @0x7ffee3d05700

对象地址: 0x7ffee3d056f0, data指向: 0x7ffee3d05700

对象地址: 0x7ffee3d056e0, data指向: 0x7ffee3d05700 // obj2.data 和 obj1.data 指向同一个地址!

析构函数调用: 释放内存 @0x7ffee3d05700 // obj2 释放了内存

析构函数调用: 释放内存 @0x7ffee3d05700 // obj1 试图再次释放同一块内存 -> 崩溃!!!

其中的问题所在就是,obj1和obj2中的data指向了同一个堆内存空间,这就导致在delete中重复删除了两次

当时我在这里有一个疑问,就是前面加了if 该地址 != nullptr 再释放为什么不可以解决呢

在delete掉第一个obj中的data时,该内存确实被释放了,但是obj2中data仍然存放了 0x7ffee3d05700,所以判断不为nullptr,所以就会再delete一次这个内存空间

三、深拷贝实现安全保障

深拷贝可以给指针成员重新分配堆内存,并将原对象指针指向的内容(不仅仅是地址)复制到新分配的内存中。这样,拷贝后的对象和原对象拥有完全独立的数据副本,不会互相影响

那我们什么时候需要深拷贝呢?

1.类成员包含指向堆内存的原始指针

2.类管理着需要独占性控制的资源(如文件句柄、网络连接等)

什么时候可以浅拷贝呢?

1.类成员只包含基本数据类型 (`int`, `float`, `char` 等)。

2.成员包含本身能正确管理拷贝的类对象 (例如 std::string, std::vector)。成员包含本身能正确管理拷贝的类对象 (例如 `std::string`, `std::vector`)

3.设计本身就是需要共享资源

四、现代C++可以避免手动深拷贝

1.使用标准库容器 (std::vector, std::string 等)

2.使用智能指针 (std::unique_ptr, std::shared_ptr)

#内存管理##深浅拷贝##大二[话题]##C++#
全部评论

相关推荐

03-06 12:44
已编辑
吉林大学 Java
是个千人厂,没听过名字。1. 做一个自我介绍。2. 你这个项目和技术栈从哪里学的?有报辅导班嘛[答 都是是自己网上学的,学校教的东西没用]3. 我看了你放在github上的项目,前端也是你写的嘛[答 AI写的,90%精力用于后端开发,前端单纯用于作为后端逻辑的可视化技术验证(骗你的其实后端也是AI写的)]4. 好,你觉得这些技术栈研究得最深刻的是哪个[答 八股压根没背到后面,昨晚背了MySQL就说MySQL]5. 那讲一下MySQL的索引[答 从B+树选型一路吟唱到联合索引,索引失效]6. 联合索引ABC问题,AB走索引嘛,BC走索引嘛?BAC走索引嘛?A or B 走索引嘛[走,不走,走,不走。面试官点头说可以]7. 讲一下项目里Redission分布式锁实现8. Watchdog机制具体是怎么工作9. 消息队列有考虑过Kafka嘛,怎么选型的10. 你这个项目消息队列可能出现什么问题,怎么解决这个问题?[瞎扯没用的,被面试官引导答了视频处理可能产生消息堆积问题,然后开始吟唱]11. 文件分片自己写的还是用的什么框架?上传进度的Redis数据结构?上传的视频有多大?小分片大小?12. 项目里Redis会话记忆是啥意思?[面试官说不行,没人把这个全放Redis里[生气R]]13. 那这和直接查数据库有什么区别[扯了Token成本和解决幻觉问题之类的,给面试官听笑了,我最后也没绷住]14. 你平时是怎么使用AI coding的15. 算法,给了我一个leedcode链接,一看做过了。然后换了一道三数之和,也做过了。然后面试官说算了,让我讲讲思路吧反问:1.有什么需要提高的地方2.介绍一下部门业务有哪些这个面试官真的感官非常非常好,问问题还疯狂引导,感觉不会也会了。找实习  牛客AI配图神器#
查看15道真题和解析
点赞 评论 收藏
分享
评论
3
6
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务