# A06 —— new/delete 和 malloc/free:C++ 内存管理的区别
**金句**:new 不是 malloc,delete 不是 free——它们不只是分配,还有构造和析构。
—
## new 和 malloc 的本质区别
“`
new 和 malloc 的区别:
malloc:
– C 库函数
– 只分配内存,不初始化
– 返回 void*
– 失败返回 NULL
new:
– C++ 关键字
– 分配内存 + 调用构造函数
– 返回具体类型的指针(不需要类型转换)
– 失败抛出 std::bad_alloc
// malloc 示例
int *p = (int*)malloc(sizeof(int));
*p = 42; // 必须手动初始化
// new 示例
int *p = new int(42); // 分配 + 初始化
“`
“`
new 的底层实现:
void* operator new(size_t size) {
if (size == 0) size = 1;
// 尝试分配
void *p = malloc(size);
// 分配失败,调用 new_handler
while (p == nullptr) {
std::new_handler h = std::get_new_handler();
if (h) (*h)();
else throw std::bad_alloc();
p = malloc(size);
}
return p;
}
new 实际上调用 malloc!
delete 实际上调用 free!
“`
—
## new 和 delete 对对象的作用
“`
new 对对象:
class A {
int x;
public:
A(int v) : x(v) {}
};
A *p = new A(10);
等价于:
1. void *temp = operator new(sizeof(A)); // malloc
2. A *p = static_cast(temp);
3. p->A(10); // 调用构造函数
delete 对对象:
delete p;
等价于:
1. p->~A(); // 调用析构函数
2. operator delete(p); // free
构造和析构是 new/delete 和 malloc/free 的本质区别!
“`
“`
数组的 new[] 和 delete[]:
A *arr = new A[10]; // 分配 10 个 A 对象
delete[] arr; // 销毁 10 个对象
等价于:
1. A *arr = (A*)operator new[] (10 * sizeof(A));
2. 构造 10 个对象
3. 调用 10 次析构函数
4. operator delete[] (arr)
注意:
delete[] 必须和 new[] 配对
用 delete(不带[])销毁数组会导致 UB
“`
—
## placement new
“`
placement new:在指定地址构造对象
#include
char buf[sizeof(A)];
A *p = new(buf) A(10); // 在 buf 上构造 A
等价于:
void *temp = buf;
A *p = static_cast(temp);
p->A(10);
用途:
– 预先分配的内存上构造对象
– 内存池
– 对象构造/析构灵活控制
显式析构(placement delete):
p->~A(); // 只调用析构,不释放内存
“`
—
## operator new 可以重载
“`
可以自定义 operator new:
class MyClass {
public:
static void* operator new(size_t size) {
// 自定义分配逻辑
// 比如从对象池分配
return pool.allocate(size);
}
static void operator delete(void* p) {
// 自定义释放逻辑
pool.deallocate(p);
}
};
所有 MyClass 的 new 都走这个函数。
全局 operator new 可以被所有类型使用。
“`
—
## 总结
– **malloc**:只分配内存,不初始化,返回 void*
– **new**:分配内存 + 调用构造函数,返回具体类型指针,失败抛异常
– **operator new**:底层调用 malloc,new 是 operator new + 构造
– **delete**:调用析构 + operator delete(底层 free)
– **new[]/delete[]**:构造/析构数组,必须配对使用
– **placement new**:在指定地址构造对象,不分配内存
**下篇预告(A07)**:什么是内存池?预先分配大块内存,按需分配——为什么游戏服务器常用内存池来避免 malloc。
—
*关注公众号「AI不着急」,回复”资料”获取内存学习路线图。*
评论