C++ 属性: assume (C++23 起)

来自cppreference.com
< cpp‎ | language‎ | attributes


 
 
C++ 语言
 
 
属性
assume
(C++23)
(C++14)
(C++20)
(C++17)
(C++11)
(C++20)
 

指示一个表达式在给定位置总是求值为 true,否则行为未定义。编译器可以基于此事实进行优化。

必须在任何有效输入都不能使表达式为 false 时使用。如果该表达式存在求值为 false 的可能,就会向整个程序(不仅是出现假设之处)注入未定义行为。它一定不是断言或前条件的替代品。

语法

[[assume( 表达式 )]]
表达式 - 按语境转换到 bool 的,必然求值为 true 的表达式

解释

表达式 不能是逗号表达式,但是可以通过外面包围一层圆括号来使用逗号表达式。

表达式 不会求值(但它依然会潜在求值)。

只能应用到空语句,如 [[assume(x > 0)]];。该语句被称为一条 假设。如果 表达式 不会在假设处求值为 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++23 标准(ISO/IEC 14882:2024):
  • 9.12.3 Assumption attribute [dcl.attr.assume]

参阅

标记执行的不可抵达点
(函数)

外部链接

1.  Clang 语言扩展文档:__builtin_assume
2.  Clang 属性参考文档:assume
3.  MSVC 文档:__assume 内建函数。
4.  GCC 文档:__attribute__((assume(...)))