# A06 — new/delete 和 malloc/free: C++ memory management的Difference

**金句**: new 不是 malloc, delete 不是 free — 它们不只是allocate, 还有构造和析构.

## new 和 malloc 的Essential Difference

“`
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 对对象的Role

“`
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 可以被所有类型使用。
“`

## Summary

– **malloc**: 只allocate内存, 不initialize, return void*
– **new**: allocate内存 + 调用构造函数, return具体Type指针, 失败抛exception
– **operator new**: 底层调用 malloc, new 是 operator new + 构造
– **delete**: 调用析构 + operator delete (底层 free)
– **new[]/delete[]**: 构造/析构数组, 必须配对使用
– **placement new**: 在指定地址构造对象, 不allocate内存

**下篇预告 (A07) **: What is 内存池? 预先allocate大块内存, 按需allocate — 为什么游戏服务器常用内存池来避免 malloc.

*关注公众号”AI不着急”, 回复”资料”obtain内存学习路线图. *

Last modified: 2024年7月31日

Author

Comments

Write a Reply or Comment

Your email address will not be published.