new失败默认抛异常而非返回nullptr,需nothrow才返回nullptr;delete必须严格匹配new/new[];new/delete调用构造/析构函数,非malloc/free翻版;应优先使用智能指针或vector避免裸指针管理。

new 分配失败时不会自动返回 nullptr
在较老的 C++ 标准(C++98/03)中,new 失败默认抛出 std::bad_alloc 异常,而不是返回 nullptr。如果你没写异常处理,程序会直接终止——这和很多 C 风格代码的直觉相反。
- 想让
new失败时返回nullptr,得显式用nothrow:int* p = new(std::nothrow) int[1000000]; - 检查前必须先确认是否用了
nothrow,否则if (p == nullptr)永远不会触发,但程序已在异常中崩溃 - C++11 起默认行为没变,别依赖编译器扩展或旧项目里的“好像没崩”来判断逻辑是否安全
delete 和 delete[] 必须严格匹配 new 和 new[]
用 new 分配单个对象,就必须用 delete;用 new[] 分配数组,就必须用 delete[]。混用不是“可能出问题”,而是未定义行为——可能当场崩溃、内存泄漏,也可能看似正常跑几个月后突然出错。
-
int* p = new int; delete[] p;—— 错,delete[]会尝试读取隐藏的数组长度信息,而new没写这个 -
int* p = new int[10]; delete p;—— 错,delete不会调用多个析构函数,也不会释放整个数组块 - 现代写法更推荐用
std::vector或std::unique_ptr,从根本上避开匹配问题
new/delete 不是 malloc/free 的 C++ 翻版
new 不仅分配内存,还会调用构造函数;delete 不仅释放内存,还会调用析构函数。这是本质区别,也是很多人踩坑的根源。
- 对自定义类型,
malloc+free完全绕过构造/析构,对象处于未初始化或半销毁状态 -
new内部可能调用malloc,但你不能假设它一定这么干;不同编译器、STL 实现可能有不同内存管理策略 - 重载类内的
operator new时,只负责内存分配,构造函数仍由编译器插入调用——别在里面手动new对象再return
没有异常安全的裸 new/delete 组合
如果 new 后面的代码抛异常(比如另一个 new 失败、文件打开失败),而你又没用 RAII 封装,delete 就永远不会执行。
立即学习“C++免费学习笔记(深入)”;
- 典型反模式:
auto p = new int[100]; do_something_that_might_throw(); delete[] p;——do_something...抛异常,p泄漏 - 正确做法:立即用
std::unique_ptr<int> p(new int[100]);</int>,异常发生时自动释放 - 即使你写了
try/catch,也要注意资源获取即初始化(RAII)比手动管理更可靠、更少出错
动态内存真正的复杂点不在语法,而在生命周期归属是否清晰。只要指针一离开作用域就没人管它,哪怕语法完全正确,也迟早出事。











