assert

来自cppreference.com
< cpp‎ | error


在标头 <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。诊断信息要求包含 expression 的文本,以及预定义变量 __func__ (C++11 起)预定义宏 __FILE____LINE__ 的值。

(C++26 前)

assert 会往程序中加入一个诊断测试,并展开成一个类型 void 的表达式。对 __VA_ARGS__ 进行求值,并将它按语境转换到 bool

  • 如果求值产生 true,那么 assert 后面不做任何事。
  • 否则,展开后的表达式会以由实现定义的格式在标准错误流上创建诊断信息,并调用 std::abort()。诊断信息包含 #__VA_ARGS__ 和原文件名、源代码行号以及外围函数名等信息(例如 std::source_location::current() 提供的结果)。
(C++26 起)


如果满足以下条件之一,那么表达式 assert(E) 保证是常量子表达式

  • 在最后定义或重定义 assert 的位置已经定义了 NDEBUG
  • E 按语境转换到 bool 后,是求值为 true 的常量子表达式。
(C++17 起)

参数

condition - 标量类型的表达式

返回值

(无)

注解

因为 assert仿函数宏,在实参中未被括号保护的逗号都被转译成宏实参的分隔符。这种逗号常能在模板实参列表和列表初始化中找到:

assert(std::is_same_v<int, int>);        // 错误:assert 不接收两个参数
assert((std::is_same_v<int, int>));      // OK:一个实参
static_assert(std::is_same_v<int, int>); // OK:不是宏
std::complex<double> c;
assert(c == std::complex<double>{0, 0});   // 错误
assert((c == std::complex<double>{0, 0})); // OK
(C++26 前)

没有标准化的添加消息到 assert 错误的接口。一个包含它的方式是使用逗号运算符,只要它未被重载,或者和字符串字面量一起使用 &&

assert(("有五盏灯", 2 + 2 == 5));
assert(2 + 2 == 5 && "有五盏灯");

assertMicrosoft CRT 中的实现不遵从 C++11 以及后续标准版本,因为它的底层函数(_wassert)不接收 __func__ 或等价的替代品。

虽然 C23/C++26 中 assert 的更改不是正式的缺陷报告, C 委员会推荐实现将该更改向后移植到旧模式。

示例

#include <iostream>
// 去注释以禁用 assert()
// #define NDEBUG
#include <cassert>
 
// 使用 (void) 关闭“未使用”警告
#define assertm(exp, msg) assert(((void)msg, exp))
 
int main()
{
    assert(2 + 2 == 4);
    std::cout << "检查点 #1\n";
 
    assert((void("void 可以避免“未使用值”警告"), 2 * 2 == 4));
    std::cout << "检查点 #2\n";
 
    assert((010 + 010 == 16) && "另一种添加断言信息的方式");
    std::cout << "检查点 #3\n";
 
    assertm((2 + 2) % 3 == 1, "成功");
    std::cout << "检查点 #4\n";
 
    assertm(2 + 2 == 5, "失败"); // 断言失败
    std::cout << "在最后一个断言后继续执行\n"; // 不会输出
}

可能的输出:

检查点 #1
检查点 #2
检查点 #3
检查点 #4
main.cpp:23: int main(): Assertion `((void)"失败", 2 + 2 == 5)' failed.
Aborted

参阅

static_assert declaration (C++11) 进行编译时断言检查
导致非正常的程序终止(不进行清理)
(函数)