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(...))) 。
|