C++中的assert
基本概念
在 C++ 中,assert
是一个用于在程序运行时进行调试的宏。它主要用于检测程序中的假设条件是否为真,以帮助开发者发现并定位错误。assert 通常在调试阶段使用,而在发布(release)版本中会被禁用,从而避免对性能产生影响。
基本用法
要使用 assert,需要包含头文件 <cassert>
:
#include <cassert>
然后,可以在代码中使用 assert 宏来检查一个表达式是否为真。例如:
#include <cassert>
#include <iostream>
int factorial(int n) {
assert(n >= 0); // 确保 n 是非负数
if (n == 0) return 1;
return n * factorial(n - 1);
}
int main() {
int number = 5;
std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl;
number = -3;
std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl; // 这里会触发断言
return 0;
}
输出如下:
在上述代码中,当 factorial 函数被调用时,如果传入的参数 n 为负数,assert(n >= 0); 将会触发断言失败,程序会中止执行并输出错误信息。
工作原理
-
调试模式:在调试模式下(通常未定义 NDEBUG 宏),assert 会检查表达式的真假。如果表达式为假,程序会输出错误信息并调用 abort() 函数终止程序。
-
发布模式:在发布模式下(通常定义了 NDEBUG 宏),所有的 assert 语句都会被忽略,编译器会将其移除。这意味着在发布版本中,assert 不会对性能产生任何影响。
要在发布模式中禁用 assert,可以在编译时定义 NDEBUG 宏,例如:
g++ -D NDEBUG -o my_program my_program.cpp
补充(使用NDEBUG宏)
在代码中定义NDEBUG宏
直接在代码中定义DEBUG宏时,如下:
#include <cassert>
#include <iostream>
#define NDEBUG
int factorial(int n) {
assert(n >= 0); // 确保 n 是非负数
if (n == 0) return 1;
return n * factorial(n - 1);
}
int main() {
int number = 5;
std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl;
number = -3;
std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl; // 这里会触发断言
return 0;
}
输出如下:
尽管定义了 NDEBUG 宏,但断言 (assert) 仍然触发错误输出。
是不是很奇怪?
其实是个顺序问题。
assert 宏的行为取决于 NDEBUG 宏是否在包含 <cassert>
之前被定义。
由于在包含 <cassert>
之后才定义 NDEBUG,预处理器在处理 #include <cassert>
时,NDEBUG 还未被定义,因此 assert 宏仍然处于启用状态。这导致即使在代码中定义了 NDEBUG,断言依然会生效。
如何解决这个问题呢?
正确代码如下:
#define NDEBUG
#include <cassert>
#include <iostream>
int factorial(int n) {
assert(n >= 0); // 确保 n 是非负数
if (n == 0) return 1;
return n * factorial(n - 1);
}
int main() {
int number = 5;
std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl;
number = -3;
std::cout << "Factorial of " << number << " is " << factorial(number) << std::endl; // 这里会触发断言
return 0;
}
在Visual Studio不启动调试输出如下:
在Visual Studio启动调试是这样的:
要将 #define NDEBUG
放在include <cassert>
之前
通过编译器选项定义 NDEBUG:
比如:
g++ -D NDEBUG -o my_program my_program.cpp
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现