C++中的new和delete与C中的malloc,calloc、relloc与free函数-AI回答
特性语言C / C++C++分配 / 释放函数调用运算符数组版本无专用版本(手动计算大小)new[]delete[]返回类型void*,需强转返回具体类型指针构造 / 析构不调用会调用失败处理返回NULL抛出异常(或nothrow返回nullptr重载能力无可重载底层关系C++ 的new常调用malloc实现内部可能调用mallocfree✅结论C++ 中优先使用newdelete(它们是类型安全
·
好的,这个问题是 C 和 C++ 内存管理对比 的核心问题之一,我帮你系统梳理一下 new
/ delete
与 malloc
/ calloc
/ realloc
/ free
的区别与联系。
本人注解:首先需明确,这都是在堆上分配和释放内存的关键字或函数(严格来讲都是函数)
从这几个函数也可以看出C也好或C++也好都没有管理内存自动申请和释放的机制,这一点和java、python还是很有区别的
1. 归属与定位
特性 | C 语言 | C++ |
---|---|---|
分配 / 释放方式 | 函数调用 | 运算符(关键字) |
头文件 | <stdlib.h> |
<new> (delete 不需要头文件) |
适用场景 | C 和 C++ 都可用 | 仅 C++ 可用 |
有一点需要明确,c++中也是可以使用 malloc
/ calloc
/ realloc
/ free这些函数的,而c中则是不能使用new和delete的
2. 功能对应关系
C 语言 | C++ 等价 | 说明 |
---|---|---|
malloc(size) |
new |
分配内存 |
calloc(num, size) |
new + 初始化(或 std::vector ) |
分配并初始化为 0 |
realloc(ptr, size) |
无直接等价,需手动拷贝 | 重新分配大小 |
free(ptr) |
delete |
释放内存 |
malloc(n*size) + memset(0) |
new T[n] (C++11 后可值初始化) |
数组分配并清零 |
3. 核心区别
以下从返回指针类型的处理,以及对C++特有的构造析构函数的调用,失败处理的方式和内存管理方面来详细解释不同之处,使用时也需非常注意
(1) 类型安全
malloc
/calloc
/realloc
- 返回
void*
,需要强制类型转换 - 不检查类型大小是否正确(完全依赖程序员)
c运行
int *p = (int*)malloc(sizeof(int));
- 返回
new
- 返回具体类型的指针,无需强制转换(这一点需要关注和知道)
- 编译器会自动计算所需内存大小
cpp运行
int *p = new int;
(2) 构造函数 / 析构函数调用
malloc
/free
- 只分配 / 释放原始内存,不会调用对象的构造函数或析构函数
c运行
struct Test { Test() { printf("Construct\n"); } ~Test() { printf("Destruct\n"); } }; Test *t = (Test*)malloc(sizeof(Test)); // 不会打印 "Construct" free(t); // 不会打印 "Destruct"
new
/delete
new
会调用对象的构造函数delete
会调用对象的析构函数
本人注:关于对构造函数和析构函数的区别,其实也非常好理解,构造函数和析构函数本身就是C++中独有的概念
cpp运行
Test *t = new Test; // 打印 "Construct" delete t; // 打印 "Destruct"
(3) 数组内存管理
- C 语言
malloc(n * sizeof(T))
分配数组,不会调用构造 / 析构- 释放用
free
c运行
int *arr = (int*)malloc(10 * sizeof(int)); free(arr);
- C++
new T[n]
分配数组,会调用每个元素的构造函数delete[]
释放数组,会调用每个元素的析构函数
cpp运行
Test *arr = new Test[3]; // 3次构造 delete[] arr; // 3次析构
⚠ 必须配对使用
new[]
/delete[]
,否则行为未定义
(4) 失败处理
malloc
/calloc
/realloc
- 失败时返回
NULL
- 需要手动检查返回值
c
运行
int *p = (int*)malloc(sizeof(int)); if (p == NULL) { /* 处理错误 */ }
- 失败时返回
new
- 失败时抛出
std::bad_alloc
异常 - 可以用 nothrow 版本返回
NULL
cpp
运行
int *p = new(std::nothrow) int; if (p == nullptr) { /* 处理错误 */ }
- 失败时抛出
(5) 自定义内存管理
- C++ 可以重载
operator new
/operator delete
控制内存分配方式 - C 没有直接的重载机制,只能自己写分配 / 释放函数
4. 联系
- 底层关系在大多数 C++ 实现中,
new
内部会调用malloc
分配内存,delete
内部会调用free
释放内存 - 混合使用(不推荐)
malloc
分配的内存不能用delete
释放(会跳过析构函数,可能崩溃)new
分配的内存不能用free
释放(可能导致未定义行为)- 数组版本同样不能混用
5. 代码示例对比
单个对象
cpp
运行
// C
int *p1 = (int*)malloc(sizeof(int));
*p1 = 42;
free(p1);
// C++
int *p2 = new int(42); // 直接初始化
delete p2;
数组
cpp
运行
// C
int *arr1 = (int*)malloc(10 * sizeof(int));
free(arr1);
// C++
int *arr2 = new int[10](); // 值初始化,全部为0
delete[] arr2;
类对象
cpp
运行
struct Test {
Test() { printf("Construct\n"); }
~Test() { printf("Destruct\n"); }
};
// C++
Test *t = new Test; // 构造
delete t; // 析构
// C(不会调用构造/析构)
Test *t2 = (Test*)malloc(sizeof(Test));
free(t2);
6. 总结对比表
特性 | malloc / calloc / realloc / free | new / delete |
---|---|---|
语言 | C / C++ | C++ |
分配 / 释放 | 函数调用 | 运算符 |
数组版本 | 无专用版本(手动计算大小) | new[] / delete[] |
返回类型 | void* ,需强转 |
返回具体类型指针 |
构造 / 析构 | 不调用 | 会调用 |
失败处理 | 返回 NULL |
抛出异常(或 nothrow 返回 nullptr ) |
重载能力 | 无 | 可重载 operator new/delete |
底层关系 | C++ 的 new 常调用 malloc 实现 |
内部可能调用 malloc / free |
✅ 结论:
- C++ 中优先使用
new
/delete
(它们是类型安全的,并会调用构造 / 析构函数) - 与 C 库或底层 API 交互时,才使用
malloc
/free
- 绝对不要混用
malloc
+delete
或new
+free
- 对于动态数组,C++ 推荐使用
std::vector
而不是手动new[]
更多推荐
所有评论(0)