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 后面不做任何事。
  • 否则 assert 会在标准错误流上创建诊断信息,并调用 std::abort()
(C++26 前)

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

  • 如果求值产生 true,那么 assert 后面不做任何事。
  • 否则 assert 会在标准错误流上创建诊断信息,并调用 std::abort()
(C++26 起)

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

  • expression 的文本
(C++26 前)
  • #__VA_ARGS__
(C++26 起)

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

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

目录

[编辑]参数

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__ 或等价的替代品。

从 C++20 开始,诊断信息所需的值也可以通过 std::source_location::current() 获取。

虽然 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

[编辑]缺陷报告

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

缺陷报告 应用于 出版时的行为 正确行为
LWG 2234 C++11 assert 无法在常量表达式中使用 可以使用

[编辑]参阅

contract_assert 语句(C++26) 在执行中验证一项内部条件[编辑]
static_assert 声明(C++11) 进行编译时断言检查[编辑]
导致非正常的程序终止(不进行清理)
(函数)[编辑]
assert 的 C 文档
close