命名空间
变体
操作

assert

来自 cppreference.cn
< cpp‎ | 错误
定义于头文件 <cassert>
禁用断言
(1)
#define assert(condition) ((void)0)
(直到 C++26)
#define assert(...)       ((void)0)
(C++26 起)
启用断言
(2)
#define assert(condition) /* 未指定 */
(直到 C++26)
#define assert(...)       /* 未指定 */
(C++26 起)

assert 的定义取决于另一个宏 NDEBUG,该宏并非由标准库定义。

1) 如果在源代码中包含 <cassert><assert.h> 的位置,NDEBUG 被定义为宏名,则断言被禁用:assert 不执行任何操作。
2) 否则,断言被启用

assert 检查其参数(必须是标量类型)

  • 如果参数不等于零,则没有进一步的效果。
  • 否则,assert 在标准错误流上创建诊断信息并调用 std::abort()
(直到 C++26)

assert 将诊断测试放入程序中,并扩展为 void 类型的表达式。__VA_ARGS__ 被评估并上下文转换为 bool

  • 如果评估结果为 true,则没有进一步的效果。
  • 否则,assert 在标准错误流上创建诊断信息并调用 std::abort()
(C++26 起)

诊断信息具有实现定义的格式,但它始终包含以下信息

  • condition 的文本
(直到 C++26)
  • #__VA_ARGS__
(C++26 起)

表达式 assert(E) 保证是一个常量子表达式,如果以下任一情况成立:

  • NDEBUGassert 最后一次定义或重新定义的位置被定义,或者
  • E上下文转换为 bool,是一个评估为 true 的常量子表达式。
(C++11 起)

目录

[编辑] 参数

条件 - 标量类型的表达式

[编辑] 注意

因为 assert 是一个函数式宏,参数中任何未被括号保护的逗号都将被解释为宏参数分隔符。此类逗号常见于模板参数列表和列表初始化中

assert(std::is_same_v<int, int>);        // error: assert does not take two arguments
assert((std::is_same_v<int, int>));      // OK: one argument
static_assert(std::is_same_v<int, int>); // OK: not a macro
 
std::complex<double> c;
assert(c == std::complex<double>{0, 0});   // error
assert((c == std::complex<double>{0, 0})); // OK
(直到 C++26)

没有标准化接口可以向 assert 错误添加额外消息。一种可移植的方法是使用逗号运算符,前提是它没有被重载,或者使用 && 和字符串字面量

assert(("There are five lights", 2 + 2 == 5));
assert(2 + 2 == 5 && "There are five lights");

Microsoft CRT 中 assert 的实现不符合 C++11 及更高版本,因为其底层函数(_wassert)既不接受 __func__ 也不接受等效替代。

自 C++20 起,诊断消息所需的数值也可以通过 std::source_location::current() 获取。

尽管 C23/C++26 中 assert 的更改并非正式的缺陷报告,但 C 委员会建议实现将此更改反向移植到旧模式。

[编辑] 示例

#include <iostream>
// uncomment to disable assert()
// #define NDEBUG
#include <cassert>
 
// Use (void) to silence unused warnings.
#define assertm(exp, msg) assert((void(msg), exp))
 
int main()
{
    assert(2 + 2 == 4);
    std::cout << "Checkpoint #1\n";
 
    assert((void("void helps to avoid 'unused value' warning"), 2 * 2 == 4));
    std::cout << "Checkpoint #2\n";
 
    assert((010 + 010 == 16) && "Yet another way to add an assert message");
    std::cout << "Checkpoint #3\n";
 
    assertm((2 + 2) % 3 == 1, "Success");
    std::cout << "Checkpoint #4\n";
 
    assertm(2 + 2 == 5, "Failed"); // assertion fails
    std::cout << "Execution continues past the last assert\n"; // No output
}

可能的输出

Checkpoint #1
Checkpoint #2
Checkpoint #3
Checkpoint #4
main.cpp:23: int main(): Assertion `((void)"Failed", 2 + 2 == 5)' failed.
Aborted

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
LWG 2234 C++11 assert 不能用于常量表达式 可以使用

[编辑] 参阅

contract_assert 语句 (C++26) 在执行期间验证内部条件[编辑]
static_assert 声明 (C++11) 执行编译时断言检查[编辑]
导致程序异常终止(不进行清理)
(函数) [编辑]
C 文档 关于 assert