std::nothrow 是一个类型为 std::nothrow_t 的标准库对象,用于重载 operator new,使内存分配失败时返回 nullptr 而非抛出 std::bad_alloc 异常;它必须显式写在 new 后的圆括号中,仅适用于原始 new 表达式,不改变分配逻辑,也不抑制构造函数异常。

std::nothrow 是什么,它怎么改写 new 的行为
默认的 new 在内存分配失败时会抛出 std::bad_alloc 异常;而传入 std::nothrow 作为参数后,new 改为返回 nullptr,不抛异常。这不是一个开关或宏,而是重载的 operator new 版本,类型为 std::nothrow_t,由标准库提供。
关键点:必须显式传入,且只能用于原始 new 表达式(不能用于 new[] 的等价写法,但 new[] 也有对应重载)。
正确写法:语法、括号、类型匹配缺一不可
常见错误是漏掉括号、写错大小写,或误以为能用在任意位置。正确调用格式只有一种:
int* p = new (std::nothrow) int[1000000000];
注意以下细节:
立即学习“C++免费学习笔记(深入)”;
-
std::nothrow必须写在new后面的圆括号里,不能放在类型后或分号前 - 必须带
std::命名空间,不能只写nothrow - 它和 placement new 的参数位置相同,但语义不同:这里不是“放置到某地址”,而是“请别抛异常”
- 对数组同样有效:
new (std::nothrow) char[4096]
返回 nullptr 后必须手动检查,否则行为未定义
使用 std::nothrow 不代表可以跳过空指针判断——它只是把异常路径转成显式检查路径。一旦忽略,后续解引用就会崩溃。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
典型安全写法:
auto p = new (std::nothrow) double[1024 * 1024];
if (!p) {
// 处理分配失败:日志、降级、返回错误码等
return nullptr;
}
// 正常使用 p...
delete[] p;容易踩的坑:
- 忘记检查就直接
memset(p, 0, ...)或p[0] = 1→ 段错误 - 在函数内部分配后未返回或未清理,导致上层无法感知失败
- 和
std::unique_ptr混用时没适配:智能指针构造不会自动识别std::nothrow,需手动传入原始指针并判空
它不改变底层分配逻辑,也不提升性能或兼容性
std::nothrow 只影响失败时的控制流出口,不参与内存搜索策略、不绕过 malloc、不降低开销。它的作用纯粹是“把 throw 换成 return nullptr”。
几个事实:
- 在嵌入式或无异常环境(编译选项
-fno-exceptions)中,std::nothrow是唯一可用的new形式;否则链接会失败 - 它和
malloc的失败行为相似,但对象构造仍可能发生异常(例如类的构造函数抛异常时,new (std::nothrow)仍会释放内存并返回nullptr) - 不要指望它让分配“更容易成功”——如果系统没内存,它照样返回
nullptr
真正容易被忽略的是:构造函数异常时的行为和内存是否已释放,这和 std::nothrow 的语义耦合紧密,但文档极少强调。

















