new与delete必须严格配对:new配delete、new[]配delete[],混用将导致未定义行为,如析构函数调用错误、内存泄漏或崩溃;释放后应置nullptr以防野指针。

new 和 delete 的基本用法和配对原则
必须严格配对使用,new 出来的指针只能用 delete 释放,new[] 分配的数组必须用 delete[] 释放——混用会触发未定义行为,常见表现是程序崩溃或内存泄漏。
典型错误现象:delete 一个 new[] 得到的指针,可能只析构第一个元素,其余对象不调用析构函数;用 delete[] 释放单个对象,则可能读取非法元数据地址。
-
int* p = new int(42);→ 必须用delete p; -
int* arr = new int[10];→ 必须用delete[] arr; - 不要对
nullptr调用delete(虽然标准允许,但掩盖逻辑缺陷) - 释放后立即置为
nullptr,避免重复释放:delete p; p = nullptr;
new 失败时怎么处理而不是直接崩溃
默认情况下,new 在内存不足时抛出 std::bad_alloc 异常,不是返回 nullptr。如果没捕获,程序终止——这在嵌入式或实时系统中不可接受。
两种应对方式:
- 显式使用
nothrow版本:int* p = new (std::nothrow) int[1000];,失败时返回nullptr,需手动判空 - 全局重载
operator new,自定义分配失败策略(慎用,影响整个程序) - 不建议用
set_new_handler,它只影响抛异常路径,且 handler 本身不能抛异常或返回
为什么推荐用智能指针而不是裸 new/delete
裸 new/delete 容易漏掉释放、异常路径绕过释放、或提前释放后继续访问——这些都难调试。
现代 C++ 的替代方案更安全:
-
std::unique_ptr→ 离开作用域自动p(new int(42)); delete -
std::unique_ptr→ 自动用arr(new int[100]); delete[] -
std::shared_ptr适合需要共享所有权的场景,但注意循环引用 - 容器如
std::vector内部已管理动态内存,优先用它代替手写new int[n]
new 表达式背后实际做了什么
new 不是原子操作:它先调用分配函数(如 operator new)获取原始内存,再在该内存上调用构造函数;delete 则先调用析构函数,再调用 operator delete 归还内存。
这意味着:
- 类可重载
operator new和operator delete实现定制分配器(比如内存池) - placement new(如
new (buf) T())跳过内存分配,只调用构造函数——对应必须手动调用析构函数,不能用delete - 没有 “placement delete”,异常发生在构造中时,需按规则匹配调用对应的
operator delete防止内存泄漏
真正难的不是语法,是理解分配/构造/析构/回收这四步的边界——尤其在自定义内存管理和异常安全之间。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











