assert在release模式下被预处理器整行剔除,因ndebug宏默认启用;它仅用于调试,不可含副作用,非运行时校验手段。
assert 在 Release 模式下直接消失,不是“没生效”而是被编译器删了
这是最常让人懵圈的一点:代码里写了 assert(ptr != nullptr),Debug 下报错停住,一跑 Release 就像没写过——不是 bug,是标准行为。C++ 的 assert 本质是宏,定义在 <cassert></cassert> 中,依赖预处理符号 NDEBUG:只要定义了它(MSVC / GCC 默认在 Release 配置中定义),所有 assert 行都会被预处理器整行剔除,不占空间、不耗时间、也不检查。
所以别指望它在生产环境兜底。真要运行时校验,得用自定义断言或 if + std::terminate。
- 调试阶段放心用,但别把它当逻辑分支来写副作用,比如
assert(x++ > 0)—— Release 下x根本不加 - 跨平台项目注意:某些嵌入式工具链可能默认定义
NDEBUG,即使在 Debug 构建中 - 想临时禁用所有 assert?加编译选项
-DNDEBUG;想强制启用?确保构建时不定义它,或手动#undef NDEBUG(不推荐)
assert 参数必须是纯表达式,不能带 std::cout 或 throw
assert 接收一个 C 风格的“可求值表达式”,求值结果转为 bool。一旦表达式里出现副作用操作(尤其是流输出、函数调用、异常抛出),Debug 和 Release 行为会彻底割裂:
-
assert(ptr && "ptr is null");✅ 合法:字符串字面量只是地址,无副作用 assert(ptr || (std::cout ❌ 危险:Release 下整个右边被删,<code>std::cout不执行;Debug 下虽能打印,但违反 assert 本意(它只该用于诊断,不该负责日志)-
assert(func());❌ 隐患:如果func()有状态变更(如修改全局变量、分配资源),Release 下这行消失,逻辑就变了
真正需要日志+断言的场景,用 if (!cond) { log(); std::terminate(); } 更可控。
立即学习“C++免费学习笔记(深入)”;