new/delete 与 malloc/free 的异同
在 C++ 中,new/delete 和 malloc/free 都可以用于动态内存分配,但它们有很多本质上的不同。主要区别包括:
- 语法
- 是否调用构造/析构函数
- 返回类型
- 是否需要手动指定内存大小
- 异常处理
- 可重载性
1. new/delete(C++)
new 和 delete 是 C++ 运算符,用于动态分配和释放对象,并且自动调用构造函数和析构函数。
(1)基本语法
// 分配单个对象
ClassName* obj = new ClassName(); // 调用构造函数
delete obj; // 调用析构函数
// 分配数组
ClassName* arr = new ClassName[5]; // 调用 5 次构造函数
delete[] arr; // 调用 5 次析构函数
(2)特点
✅ 自动调用构造函数和析构函数
✅ 不需要指定内存大小(new 通过 sizeof 自动计算)
✅ 支持重载(可以自定义 operator new)
✅ 分配失败时抛出 std::bad_alloc 异常(可以用 nothrow 处理)
2. malloc/free(C 语言)
malloc 和 free 是 C 语言 的标准库函数,用于在 堆(heap)上分配和释放内存。malloc 不会调用构造函数,free 不会调用析构函数。
(1)基本语法
// 分配单个对象
ClassName* obj = (ClassName*)malloc(sizeof(ClassName)); // 需要强制类型转换
free(obj);
// 分配数组
ClassName* arr = (ClassName*)malloc(5 * sizeof(ClassName));
free(arr);
(2)特点
❌ 不会调用构造函数和析构函数(必须手动 memset() 初始化)
❌ 必须手动指定大小(malloc(sizeof(ClassName)))
❌ 不会抛出异常(返回 NULL 表示分配失败)
❌ 不支持重载
3. new/delete vs malloc/free 对比
| 特性 | new/delete(C++) | malloc/free(C) |
|---|---|---|
| 调用构造/析构函数 | ✅ 调用构造函数/析构函数 | ❌ 不会调用,需手动初始化和清理 |
| 需要手动指定大小 | ❌ 不需要(new 自动计算) | ✅ 需要(必须使用 sizeof) |
| 返回类型 | ✅ 返回正确的类型(无需强制转换) | ❌ 返回 void*,需要强制转换 |
| 失败处理 | ❌ 抛出 std::bad_alloc 异常(可用 nothrow 处理) | ✅ 返回 NULL,需手动判断 |
| 适用语言 | ✅ C++ | ✅ C 语言(C++ 也能用,但不推荐) |
| 性能 | ✅ 更优化,底层可能会重载 operator new 进行优化 | ❌ 较少优化,底层直接调用 malloc |
| 数组分配 | ✅ new[] 和 delete[] 需要成对使用 | ❌ 直接 malloc/free,无数组管理 |
4. 什么时候用 new/delete,什么时候用 malloc/free?
| 场景 | 推荐方法 | 说明 |
|---|---|---|
| 动态分配对象 | new/delete | C++ 代码中应优先使用 new,因为它会调用构造/析构函数 |
| 动态分配数组 | new[]/delete[] | 适用于 C++ 的数组对象,如 std::vector |
分配 POD 类型数据(如 char*、int*) | malloc/free | malloc 在 C 语言和某些性能敏感的场景下更合适 |
| C 和 C++ 兼容代码 | malloc/free | C 语言项目中只能使用 malloc/free |
| 异常安全性 | new/delete | new 遇到失败时抛出异常,而 malloc 返回 NULL |
5. new 失败时的 nothrow 处理
默认情况下,如果 new 失败,会抛出 std::bad_alloc 异常:
try {
int* p = new int[1000000000000]; // 可能失败
} catch (std::bad_alloc& e) {
std::cout << "Allocation failed: " << e.what() << std::endl;
}
如果不希望抛异常,可以使用 nothrow:
int* p = new(std::nothrow) int[1000000000000];
if (!p) {
std::cout << "Memory allocation failed!" << std::endl;
}
但 malloc 直接返回 NULL,无需 try-catch。
6. operator new/delete 的重载
C++ 允许重载 operator new 和 operator delete,用于自定义内存管理:
#include <iostream>
class MyClass {
public:
void* operator new(size_t size) {
std::cout << "Custom new for size: " << size << std::endl;
return malloc(size); // 使用 malloc 分配内存
}
void operator delete(void* ptr) {
std::cout << "Custom delete" << std::endl;
free(ptr); // 释放内存
}
};
int main() {
MyClass* obj = new MyClass();
delete obj;
return 0;
}
输出:
Custom new for size: 1
Custom delete
这种技术通常用于高性能系统,如游戏引擎或数据库,自定义内存池管理,提高分配效率。
7. 结论
✅ new/delete 适用于 C++,尤其是对象管理
- 会 调用构造函数和析构函数,适用于对象创建和销毁。
new失败时抛出std::bad_alloc异常。new[]需要和delete[]搭配使用。
✅ malloc/free 适用于 C 语言,或分配 POD 类型数据
- 不会调用构造/析构函数,适合简单数据结构,如
char*、int*。 - 返回
void*,需要手动转换类型。 - 返回
NULL失败,不抛异常,适用于低级别 C 代码。
在 C++ 项目中,推荐尽量使用 new/delete,因为它们更安全、更可读、更符合 C++ 语法风格。而在 C 语言或对异常不敏感的系统代码中,可以使用 malloc/free。
🔥 总结
| 特性 | new/delete(C++ 推荐) | malloc/free(C 语言) |
|---|---|---|
| 构造/析构 | ✅ 自动调用 | ❌ 需要手动初始化/释放 |
| 返回类型 | ✅ 直接返回对象指针 | ❌ 返回 void*,需强制转换 |
| 失败处理 | ❌ 抛出异常 std::bad_alloc | ✅ 返回 NULL |
| 适用场景 | ✅ C++,对象管理 | ✅ C 语言,POD 类型数据 |
1449

被折叠的 条评论
为什么被折叠?



