new/delete的配对使用与内存管理最佳实践
C++中new和delete的配对规则是什么?new[]必须匹配delete[]的原理是什么?new/delete与malloc/free混合使用会有什么问题?什么是placement delete以及何时需要?
回答
苦行僧
配对规则:
new↔delete(单个对象)new[]↔delete[](对象数组)malloc↔free(C风格)
为什么必须配对:
- new[]在分配的内存前额外存储元素计数(实现相关),delete[]读取该计数并遍历逆序析构每个元素
- 用delete代替delete[]:只析构第一个元素且释放的内存区域不对齐(计数区域被跳过)→ UB/崩溃
- 用delete[]代替delete:错误读取计数→ 可能尝试析构不存在的元素→ UB
混用new/malloc的危害:
malloc分配 + delete释放:delete调用operator delete释放,但operator delete默认用free()实现——不同堆管理器可能出错new分配 + free释放:不调用析构函数→ 资源泄漏- 结果:未定义行为,可能崩溃、挂起或静默损坏
placement delete(new处理函数):
struct T {
static void* operator new(size_t, void* buf) { return buf; }
// 对应的delete(不常用)
static void operator delete(void*, void*) {}
};
当构造函数抛出异常时,运行时自动调用与new匹配的delete释放已分配内存。对于placement new,如果构造函数抛出,需要匹配的placement delete来清理。如果未提供placement delete且构造函数抛出,编译器不会调用任何释放函数——需要手动管理。
最佳实践:
- 不要混用new/delete和malloc/free
- 使用智能指针自动管理配对
- 自定分配器时提供成对的operator new/delete
- C++中使用new/delete而非malloc/free(RAII/类型安全)
- 使用
make_unique/make_shared避免显式new