
博主名称:deM0one
⭐️C++专栏:
C++
文章目录
-
- @[toc]
- C++ 内存管理详解(new/delete 与内存分区)
-
- 一、引言
- 二、类与对象收尾:对象拷贝时的编译器优化
-
- 2.1 编译器为什么会优化拷贝
- 2.2 常见的优化场景
- 2.3 演示与结论
- 三、C++ 程序的内存分区
-
- 3.1 四大区域
- 3.2 指针与指向的内容可能在不同区域
- 3.3 经典练习:这些变量都在哪个区?
- 3.4 核心理解:分区实际上分的是"生命周期"
- 四、回顾 C 语言的动态内存管理
- 五、C++ 的 new / delete 关键字
-
- 5.1 基本用法
- 5.2 申请空间的同时初始化
- 5.3 自定义类型的行为
- 5.4 new 失败的处理方式
- 六、内存与虚拟内存
- 七、operator new 与 operator delete(重点)
-
- 7.1 定位
- 7.2 调用关系
- 八、new / delete 的实现原理(重点)
-
- 8.1 内置类型
- 8.2 自定义类型
- 九、new / delete 与 new[] / delete[] 的匹配(易错点)
-
- 9.1 匹配规则
- 9.2 反例演示
- 9.3 结论
- 十、总结
-
- 10.1 全文回顾
- 10.2 常见面试题自测清单
- 任何的建议与批评欢迎指出,我们共同进步!
- @[toc]
- 一、引言
- 二、类与对象收尾:对象拷贝时的编译器优化
-
- 2.1 编译器为什么会优化拷贝
- 2.2 常见的优化场景
- 2.3 演示与结论
- 三、C++ 程序的内存分区
-
- 3.1 四大区域
- 3.2 指针与指向的内容可能在不同区域
- 3.3 经典练习:这些变量都在哪个区?
- 3.4 核心理解:分区实际上分的是"生命周期"
- 四、回顾 C 语言的动态内存管理
- 五、C++ 的 new / delete 关键字
-
- 5.1 基本用法
- 5.2 申请空间的同时初始化
- 5.3 自定义类型的行为
- 5.4 new 失败的处理方式
- 六、内存与虚拟内存
- 七、operator new 与 operator delete(重点)
-
- 7.1 定位
- 7.2 调用关系
- 八、new / delete 的实现原理(重点)
-
- 8.1 内置类型
- 8.2 自定义类型
- 九、new / delete 与 new[] / delete[] 的匹配(易错点)
-
- 9.1 匹配规则
- 9.2 反例演示
- 9.3 结论
- 十、总结
-
- 10.1 全文回顾
- 10.2 常见面试题自测清单
- 任何的建议与批评欢迎指出,我们共同进步!
C++ 内存管理详解(new/delete 与内存分区)
今日学习: 类与对象收尾,编译器的自动优化何时优化,在哪里优化
一、引言
- 内存是程序运行的核心资源之一(CPU、GPU一种特殊的CPU、内存)
- 为什么要理解内存管理:写出高效、不出错的 C++ 程序
- 本篇博客的阅读路线图(先分区、再用法、后原理)
二、类与对象收尾:对象拷贝时的编译器优化
2.1 编译器为什么会优化拷贝
- 现代编译器会在不影响正确性的前提下,尽可能减少传参和返回过程中可省略的拷贝
- C++ 标准没有严格规定优化方式,由各编译器自行处理
2.2 常见的优化场景
- 同一表达式内连续拷贝的"合并优化"
- 更激进编译器的跨行、跨表达式合并优化
编译器能够将一次构造,一次拷贝构造直接优化成一次构造,减少多余的构造,提高效率。
此处编译器将一次构造,一次传值返回的拷贝构造的临时对象,优化成直接用1来构造临时对象返回,将aa的构造给优化掉了。
此处编译器却没有优化这是为什么?因为ret=f2()属于赋值拷贝,没有传值传参的过程,也不是对象的构造,所以编译器没有做激进的优化。
2.3 演示与结论

- 示例:f2().Print() 直接对临时对象调用成员函数,观察拷贝构造的调用次数(优化后为 0 次)
- 结论:理解拷贝构造与赋值重载的真实调用时机
三、C++ 程序的内存分区
3.1 四大区域
- 栈区:局部变量、函数参数,编译器自动分配释放
- 堆区:动态申请的内存,需手动管理
- 数据段(静态区):全局变量、静态变量
- 代码段(常量区):常量字符串、程序指令
3.2 指针与指向的内容可能在不同区域
- 指针变量本身在栈上,指向的内容可能在栈、堆、常量区等
3.3 经典练习:这些变量都在哪个区?

3.4 核心理解:分区实际上分的是"生命周期"
四、回顾 C 语言的动态内存管理
- 4.1 malloc / calloc / realloc / free 的基本用法
- 4.2 三者的区别(初始化与否、扩容方式)
- 4.3 为后文与 new/delete 对比做铺垫
五、C++ 的 new / delete 关键字
5.1 基本用法
- new int / new int[10],delete p / delete[] p
5.2 申请空间的同时初始化
- new int(5)
- new int[10]{1, 2, 3, 4, 5}
5.3 自定义类型的行为
- new 会调用构造函数;没有默认构造函数时需要显式传值
- delete 会调用析构函数
5.4 new 失败的处理方式
- new 失败会抛异常(区别于 malloc 返回 NULL)
- try/catch 捕获示例:申请超大空间,输出异常信息
六、内存与虚拟内存
- 6.1 32 位系统:约 4G 虚拟地址空间
- 6.2 64 位系统:2^64 个字节(约 160 多亿 G)
- 6.3 虚拟内存的直观理解(地址空间大小由系统位数决定)
七、operator new 与 operator delete(重点)
7.1 定位
- new/delete 是用户使用的操作符
- operator new/operator delete 是系统提供的全局函数
7.2 调用关系
- new 底层调用 operator new 申请空间
- delete 底层调用 operator delete 释放空间
八、new / delete 的实现原理(重点)
8.1 内置类型
- 与 malloc/free 基本类似
- 区别一:new/delete 管理单个元素,new[]/delete[] 管理连续空间
- 区别二:new 失败抛异常,malloc 失败返回 NULL
8.2 自定义类型
- new 的原理:
- 调用 operator new 申请空间
- 在申请的空间上执行构造函数
- delete 的原理:
- 在空间上执行析构函数
- 调用 operator delete 释放空间
- 关键点:new 的内核是 malloc,delete 的内核是 free
- 补充:对于内置类型,用 free 还是 delete 没有区别
九、new / delete 与 new[] / delete[] 的匹配(易错点)
9.1 匹配规则
- delete 是针对 new 的,delete[] 是针对 new[] 的
9.2 反例演示
- new A[10] 却用 delete p 会怎样
编译器对于多个对象的数组的时候会在头上多开四个字节,用于存储数组元素个数,因为B类型没有写析构函数所以编译器将多余的四字节给优化掉了,但是A写了析构函数,却错误地配置了delete,没有正确调用析构函数,释放位置错误导致报错
9.3 结论
- 二者一定要匹配使用,不要错配
十、总结
10.1 全文回顾
C++程序的内存划分与C语言基本一脉相承,这也体现了C++对C语言的兼容,C++中新增的new和delete关键字相比C语言的malloc,可以更便捷地实现内存的申请和初始化,是对代码简洁性的提升,另外对于malloc和free,new和delete,以及new[]和delete[]最好搭配使用,不可错配,减少报错和崩溃的风险。
10.2 常见面试题自测清单
- 各变量分别存在哪个区?
- new 和 malloc 的区别?
- new 一个对象经历了哪些步骤?
- delete[] 和 delete 混用会有什么问题?
网硕互联帮助中心


评论前必须登录!
注册