名稱空間
變體
操作

assert

來自 cppreference.com
< 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