一、C++ 内存管理方式
C 语言的内存管理方式在 C++ 中可以继续使用,但有些地方就无能为力,而且使用起来相对繁琐一些,因此,C++ 又提出了自己的内存管理方式:通过 new 和 delete 操作符进行动态内存管理。
1.1 new/delete 操作内置类型
void test() {
// 动态申请一个 int 类型的空间
int* ptr1 = new int;
// 动态申请一个 int 类型的空间并初始化为 10
int* ptr2 = new int(10);
// 动态申请 10 个 int 类型的空间
int* ptr3 = new int[10];
delete ptr1;
delete ptr2;
delete[] ptr3;
}
1.2 new/delete 操作自定义类型
在操作自定义类型的空间时,new 会调用构造函数,delete 会调用析构函数,而 malloc 和 free 不会。
#include <iostream>
using namespace std;
class A {
public:
A(int a = 0) : _a(a) { cout << "A():" << this << endl; }
~A() { cout << "~A():" << this << endl; }
private:
int _a;
};
int main() {
// new/delete 调用构造函数/析构函数
A* p1 = (A*)malloc(sizeof(A));
A* p2 = new A(1); // 调用构造函数
free(p1);
delete p2; // 调用析构函数
// 内置类型几乎一样
int* p3 = (int*)malloc(sizeof(int));
int* p4 = new int;
free(p3);
delete p4;
A* p5 = (int*)malloc(sizeof(A)*10);
A* p6 = new A[10];
free(p5);
delete[] p6;
return 0;
}
二、operator new 与 operator delete 函数
new 和 delete 是用户进行动态内存申请和释放的操作符,operator new 和 operator delete 是系统提供的全局函数,new 在底层调用 operator new 全局函数来申请空间,delete 在底层通过 operator delete 全局函数来释放空间。
三、new 和 delete 的实现原理
3.1 内置类型
如果申请的是内置类型的空间,new 和 malloc,delete 和 free 基本类似,不同的地方是:new/delete 申请和释放的是单个元素的元素空间,new[] 和 delete[] 申请的是连续空间,而且 new 在申请空间失败时会抛出异常,malloc 会返回 NULL。
3.2 自定义类型
- new 的原理
- 调用 operator new 函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
- delete 的原理
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用 operator delete 函数释放对象的空间
- new T[N] 的原理
- 调用 operator new[] 函数,在 operator new[] 中实际调用 operator new 函数完成 N 个对象空间的申请
- 在申请的空间上执行 N 次构造函数
- delete[] 的原理
- 在释放的对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理
- 调用 operator delete[] 释放空间,实际在 operator delete[] 中调用 operator delete 来释放空间
四、malloc/free 和 new/delete 的区别
malloc/free 和 new/delete 的共同点是:都是从堆上申请空间,并且需要用户手动释放。其不同点见如下表格:
| malloc/free | new/delete |
|---|---|
| 函数 | 操作符 |
| 申请的空间不会初始化 | 可以初始化 |
| 需要手动计算空间大小并传递 | 后跟类型即可,若为多个对象在 [] 中指定 |
| malloc 返回类型为 void*使用须强转 | new 后跟的是空间的类型 |
| malloc 申请空间失败返回 NULL 必须判空 | new 不需要判空但需要捕获异常 |
| 自定义类型对象时只会开辟空间 | 申请自定义类型对象时会调用构造函数和析构函数 |
总结
本文介绍了 C++ 中内存管理的操作符 new 和 delete,并详细介绍了他们的使用方法和基本原理同时与 C 中的 malloc 函数和 free 函数做对比,深化理解了二者的不同,便于更好的使用二者。

