C++中new分配失败抛std::bad_alloc异常而非返回nullptr,需用nothrow或智能指针避免崩溃;delete与delete[]不可混用;placement new不分配内存仅调构造函数;RAII和智能指针是内存管理首选。

new 分配失败时不会返回 nullptr,而是抛异常
这是 C++ 默认行为,和 C 的 malloc 有本质区别。如果你没捕获 std::bad_alloc,程序直接崩溃,而不是静默返回空指针。
常见错误现象:new 后没检查就解引用,结果运行时报 std::bad_alloc 或段错误;或者误以为像 C 那样要判 if (p == nullptr),结果根本进不去分支。
- 想让它返回
nullptr而非抛异常?用new (std::nothrow) int[1000] - 全局重载
operator new也能改行为,但不推荐——破坏可移植性 - 在嵌入式或无异常环境(
-fno-exceptions)下,new默认就是 nothrow 行为,但标准不保证,务必查编译器文档
delete 和 delete[] 混用会触发未定义行为
用 new 分配单个对象,必须用 delete;用 new[] 分配数组,必须用 delete[]。两者不能交叉——哪怕类型是 POD(如 int),也一样危险。
使用场景:动态创建字符串缓冲区、临时数组、对象容器底层实现等。
立即学习“C++免费学习笔记(深入)”;
-
int* p = new int[10]; delete p;→ 可能不报错,但析构函数漏调(对类类型)、内存管理元数据错乱、后续new失败 -
int* p = new int; delete[] p;→ 同样未定义,尤其在调试模式下容易触发断言或堆损坏检测 - 现代替代方案:
std::vector或std::unique_ptr<int[]>,自动匹配delete[]
placement new 不分配内存,只调用构造函数
它不走堆管理器,而是把对象“放”在你指定的内存地址上。常用于内存池、自定义容器、硬件寄存器映射等场景。
参数差异:第一个参数是 void* 地址,其余参数传给目标类型的构造函数。
- 必须手动调用析构函数:
p->~T(),不能用delete(因为没用new分配) - 常见错误:忘记调用析构函数,导致资源泄漏(比如内部持有文件句柄或锁)
- 示例:
char buf[sizeof(MyClass)]; MyClass* p = new (buf) MyClass(42); p->~MyClass();
RAII 是绕不开的底线,裸 new/delete 应该是例外
不是语法不会用,而是逻辑上不该依赖手动配对。C++11 之后,std::unique_ptr 和 std::shared_ptr 已覆盖绝大多数动态生命周期需求。
性能影响:智能指针几乎零开销(unique_ptr 是纯编译期包装),而裸 new/delete 容易因异常、提前 return、goto 导致泄漏。
- 需要数组?用
std::unique_ptr<int[]> p(new int[10]),自动调delete[] - 跨函数传递所有权?用
std::move(p),比传裸指针 + 注释“谁负责 delete”靠谱得多 - 唯一合理用裸 new/delete 的地方:写容器/内存池这类基础设施,且必须控制每个字节
真正难的不是怎么写 new,是怎么让别人(包括三个月后的你自己)确信这段内存一定被释放了——靠注释不行,靠约定不行,靠代码结构才行。










