目录
四、 malloc/free 和 new/delete的区别
一、C/C++ 内存分布
C/C++的内存分布在前面已经有过大量学习了,这里主要是做一道题目来巩固所学知识。
相信大家心里应该也有答案了,下面直接附上标准答案了,大家可以对照答案梳理复习一下。
图解:
【说明】
- 栈又叫堆栈——非静态局部变量/函数参数/返回值等等,栈是向下增长的。
- 内存映射段是高效的 I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程间通信。
- 堆用于程序运行时动态内存分配,堆是可以向上增长的。
- 数据段——存储全局数据和静态数据。
- 代码段——可执行的代码/只读常量。
二、C++中new与delete
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++提出了自己的内存管理方式:通过 new 和 delete 操作符进行动态内存管理。
2.1 new/delete 操作内置类型
接下来我们使用 malloc 和 new来开辟空间,看看 new 是如何开辟空间的。
然后我们在来看看 free 和 delete 的使用区别
注意: 申请和释放单个元素的空间,使用 new 和 delete 操作符,申请和释放连续的空间,使用 new []和delete [] ,注意类型匹配。
2.2 new/delete 操作自定义类型
在 new 和 delete 操作内置类型的时候可以发现,除了语法上有些不同,其效果没有什么区别,接下来大家注意下面的代码以及运行结果,观察一下 new/delete 和 malloc/free 的区别.
new/ delete 和 malloc/free 的最大区别是 new/delete 对于【自定义类型】除了开空间之外还会调用构造函数和析构函数。
所以,new/delete 是为自定义类型准备的,不仅会申请出自定义类型空间,还会调用构造和析构初始化和清理。
现在我们使用 new 创建5个初始化为10的自定义类型,这时我们就可以这样创建。
注意 ,这样定义不同的编译器可能不会支持,我使用的是VS2022,通常C++11标准支持好的编译器都是可以这样创建的。
new 开辟空间失败的检测方式:
new 失败,不需要检查返回值,new 失败会抛异常。
三、new和delete的实现原理
3.1 内置类型
如果申请的是内置类型的空间,new 和 malloc ,delete 和 free 基本类似,不同的地方是:new/delete 申请和释放的是单个元素的空间,new [] 和delete [] 申请的是连续空间,而且new在申请空间失败时会抛异常,malloc 会返回 NULL;
3.2 自定义类型
- new 的原理
- 调用opeartor new 申请空间
- 在申请的空间上执行构造函数,完成对象的构造。
- delete 的原理
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用opeartor delete 函数释放对象的空间。
- new T [N]的原理
- 调用 opeartor new [] 函数,在 opeartor new [] 中实际调用 opeartor new函数完成 N 个对象空间的申请
- 在申请的空间上执行N次构造函数。
- delete [N]的原理
- 在释放对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理。
- 调用 operator delete []释放空间,实际在 opeartor delete []中调用 opeartor delete 来释放空间
四、 malloc/free 和 new/delete的区别
malloc/free 和 new/delete 的共同点是:都是从堆上申请空间,并且需要用户手动释放。
不同点:
- malloc 和 free 是函数,new 和 delete 是操作符。
- malloc 申请的空间不会初始化,new 可以初始化。
- malloc 申请空间时,需要手动计算空间大小并传递,new 只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可。
- malloc 的返回值为 void* ,在使用时必须强转,new 不需要,因为new后跟的是空间的类型。
- malloc 申请空间失败时,返回的是 NULL ,因此使用时必须判空,new 不需要,但是new 需要捕获异常
- 申请自定义类对象时,malloc/free只会开辟空间,不会调用构造函数和析构函数,而new 在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。