C++ 属性: assume (C++23 起)
從 cppreference.com
< cpp | language | attributes
指示可以假設給定的表達式在給定位置總是求值為 true,以允許編譯器根據給定的信息進行優化。
目錄 |
[編輯] 語法
[[assume( 表達式 )]]
|
|||||||||
表達式 | - | (無括號的逗號表達式以外的)任意表達式 |
[編輯] 解釋
[[assume]] 只能被應用到空語句,如 [[assume(x > 0)]];。該語句被稱為一條假設 。
表達式 會按語境轉換到 bool,但不會求值(依然會潛在求值)。
- 如果轉換後的表達式 在假設出現的位置求值為 true,那麼假設不會有任何效果。
- 否則對假設求值具有運行時未定義行為。
[編輯] 註解
因為假設在不成立時會導致運行時未定義行為,所以必須小心使用它們。它們不用來提供函數的前提條件文檔或者診斷是否違反前條件。另外,不要未經檢驗就假設編譯器實際會使用任何特定的假設。
一種正確用法是連續使用斷言和假設:
assert(x > 0); // 在 NDEBUG 没有定义时检查条件,如果条件不成立则触发断言 [[assume(x > 0)]]; // 在 NDEBUG 定义时提供优化机会
[編輯] 示例
#include <cmath> void f(int& x, int y) { void g(int); void h(); [[assume(x > 0)]]; // 编译器可以假设 x 是正数 g(x / 2); // 可以生成更高效的代码 x = 3; int z = x; [[assume((h(), x == z))]]; // 编译器可以假设在调用 h 后 x 的值保持相同 // 该假设本身不会调用 h h(); g(x); // 编译器可以用 g(3); 替换该语句 h(); g(x); // 编译器不能用 g(3); 替换该语句 // 假设只在它出现的地方适用 z = std::abs(y); [[assume((g(z), true))]]; // 编译器可以假设 g(z) 会返回 g(z); // 根据上面和下面的假设,编译器可以用 g(10); 替换该语句 [[assume(y == -10)]]; // 这里 y != -10 的情况下行为未定义 [[assume((x - 1) * 3 == 12)]]; g(x); // 编译器可以用 g(5); 替换该语句 }
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
缺陷報告 | 應用於 | 出版時的行為 | 正確行為 |
---|---|---|---|
CWG 2924 | C++11 | 違背假設會導致未定義行為 | 會導致運行時未定義行為 |
[編輯] 引用
- C++23 標準(ISO/IEC 14882:2024):
- 9.12.3 Assumption attribute [dcl.attr.assume]
[編輯] 參閱
(C++23) |
標記執行的不可抵達點 (函數) |
contract_assert 語句 (C++26)
|
在執行中驗證一項內部條件 |
[編輯] 外部鏈接
1. | Clang 語言擴展文檔:__builtin_assume 。
|
2. | Clang 屬性參考文檔:assume 。
|
3. | MSVC 文檔:__assume 內建函數。
|
4. | GCC 文檔:__attribute__((assume(...))) 。
|