一、申请内存
new
:内存分配成功,返回该对象类型的指针;分配失败,抛出 bac_alloc 异常。malloc
:成功申请到内存,返回指向该内存的指针;分配失败,返回 NULL 指针。
在使用的时候 new、delete 搭配使用,malloc、free 搭配使用。
malloc 的原理:
- 当开辟的空间小于 128K 时,调用
brk()
函数,通过移动 _enddata 来实现; - 当开辟空间大于 128K 时,调用
mmap()
函数,通过在虚拟地址空间中开辟一块内存空间来实现。
malloc 的底层实现:
- brk() 函数实现原理:向高地址的方向移动指向数据段的高地址的指针 _enddata。
- mmap 内存映射原理:
- 进程启动映射过程,并在虚拟地址空间中为映射创建虚拟映射区域;
- 调用内核空间的系统调用函数 mmap(),实现文件物理地址和进程虚拟地址的一一映射关系;
- 进程发起对这片映射空间的访问,引发缺页异常,实现文件内容到物理内存(主存)的拷贝。
二、释放内存
delete
执行过程:
- 首先执行该对象所属类的析构函数;
- 进而通过调用 operator delete 的标准库函数来释放所占的内存空间。
delete 和 delete [] 的区别:
- delete 用来释放单个对象所占的空间,只会调用一次析构函数;
- delete [] 用来释放数组空间,会对数组中的每个成员都调用一次析构函数。
三、new 和 malloc 的区别,delete 和 free 的区别
- malloc、free 是库函数,而new、delete 是关键字。
- new 申请空间时,无需指定分配空间的大小,编译器会根据类型自行计算;malloc 在申请空间时,需要确定所申请空间的大小。
- new 申请空间时,返回的类型是对象的指针类型,无需强制类型转换,是类型安全的操作符;malloc 申请空间时,返回的是 void* 类型,需要进行强制类型的转换,转换为对象类型的指针。
- new 分配失败时,会抛出
bad_alloc
异常,malloc 分配失败时返回空指针。 - 对于自定义的类型,new 首先调用
operator new()
函数申请空间(底层通过 malloc 实现),然后调用构造函数进行初始化,最后返回自定义类型的指针;delete 首先调用析构函数,然后调用operator delete()
释放空间(底层通过 free 实现)。malloc、free 无法进行自定义类型的对象的构造和析构。 - new 操作符从自由存储区上为对象动态分配内存,而 malloc 函数从堆上动态分配内存。(自由存储区不等于堆)
- malloc分配的内存不够的时候,可以用realloc扩容(扩容原理)。new没用这样操作。
说明:
自由存储区与堆的区别:malloc在堆上分配的内存块,使用free释放内存,而new所申请的内存则是在自由存储区上,使用delete来释放。
堆是操作系统维护的一块内存,而自由存储是C++中通过new与delete动态分配和释放对象的抽象概念。堆与自由存储区并不等价。