【问题标题】:How to use C++20's likely/unlikely attribute in if-else statement如何在 if-else 语句中使用 C++20 的可能/不太可能属性
【发布时间】:2019-01-18 17:53:19
【问题描述】:

这个问题是关于 C++20 的 [[likely]]/[[unlikely]] 功能,而不是编译器定义的宏。

本文档 (cppreference) 仅给出了将它们应用于 switch-case 语句的示例。 这个 switch-case 示例与我的编译器 (g++-7.2) 完美编译,所以我假设编译器已经实现了这个功能,尽管它还没有在当前的 C++ 标准中正式引入。

但是当我像这样使用它们时:if (condition) [[likely]] { ... } else { ... },我收到了一个警告:

“警告:语句开头的属性被忽略[-Wattributes]”。

那么我应该如何在 if-else 语句中使用这些属性呢?

【问题讨论】:

  • 如果某个条件更有可能出现在 if 语句中,则将其放在首位
  • @Mercer 我知道;但这不是我要问的......
  • 它可能只是部分实现。从检查 g++ 文档开始,看看它是否应该被支持。
  • 正如 molbdnillo 所说;由于 c++20 标准并不完整,更不用说发布了,它取决于编译器如何集成它喜欢的新功能。
  • 你有例子可以给我们看吗?

标签: c++ gcc-warning c++20


【解决方案1】:

根据Jacksonville’18 ISO C++ Report 的示例,语法是正确的,但似乎还没有实现:

if (a>b) [[likely]] {

10.6.6 Likelihood attributes [dcl.attr.likelihood] draft

【讨论】:

  • 好的..所以目前编译器只是部分实现了这个属性。
  • @Leedehai 我想说的是,目前对即将推出的 C++20 标准的功能的一般支持纯粹是实验性的。
  • 我觉得奇怪的是,该链接中提供的 while 循环示例将可能的标记放在大括号之后,而不是像其余示例中那样放在大括号之前。
  • @Mercer,最新的 ISO 草案只是声明属性可以分配给标签或声明,因此 while (cond) [[likely]] { x(); y(); }while (cond) { [[likely]] x(); y(); } 似乎同样有效。我不确定是否仅将 first 语句标记为复合语句是否有意义,但委员会可能比我知道的更多 - 实际上这似乎很可能,知道我考虑过:-)
  • 我刚刚查看了提供的草稿中的示例,它完全省略了 while 循环的示例。时间会证明一切。
【解决方案2】:

截至今天,cppreference 声明,例如,likely(强调我的):

应用于语句以允许编译器针对情况进行优化 包括该语句的执行路径比 任何不包括此类的替代执行路径 声明。

这表明放置属性的位置是在最有可能的语句中,即:

if (condition) { [[likely]] ... } else { ... }

在使用 /std:c++latest 编译时,例如 Visual Studio 2019 16.7.0 接受此语法。

【讨论】:

    【解决方案3】:

    那么我应该如何在 if-else 语句中使用这些属性呢?

    正如您正在所做的那样,根据标准草案中给出的示例,您的语法是正确的(简化为仅显示相关位):

    int f(int n) {
        if (n > 5) [[unlikely]] {
            g(0);
            return n * 2 + 1;
        }
    
        return 3;
    }
    

    但您应该明白,此功能是一个相对较新的功能,因此在实现中可能只有 占位符 以允许您设置属性。从您的警告消息中可以看出这一点。


    您应该了解,除非最新草案和最终产品之间的某些措辞发生变化,否则即使兼容实现也能够忽略这些属性。它们对编译器非常建议,例如 C 语言中的 inline。来自最新的草稿 n4762(在给出这个答案时,我强调):

    注意:使用 possible 属性的目的是允许实现来优化包含它的执行路径比任何替代路径任意更可能的情况在语句或标签上不包含此类属性的执行。

    注意“允许”一词,而不是“强制”、“要求”或“授权”。

    【讨论】:

    • 基于__builtin_expect 移植现有代码会容易得多,例如if (likely(a>b)) { 如果我们可以在 if 语句中指定属性:if ([[likely]] a>b) {
    猜你喜欢
    • 2021-12-19
    • 2021-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 2012-11-21
    • 1970-01-01
    相关资源
    最近更新 更多