C++20提供了方便的[[likely]]
/[[unlikely]]
属性来指导代码生成。例如,您可以通过以下方式指定分支很可能被执行:
if (b) [[likely]] { /*...*/ }
同样,我们可以在 switch
语句中使用这些属性……但怎么使用呢?文档 给出了下面的示例(已稍作格式化):
switch (i) {
case 1:
[[fallthrough]];
[[likely]] case 2:
return 1;
}
明显的含义是
[[likely]]
/[[unlikely]]
在case
语句之前。互联网上似乎普遍宣传这种用法。然而,请考虑以下类似的代码(我所做的就是将
[[likely]]
移到另一个case
):switch (i) {
[[likely]] case 1:
[[fallthrough]];
case 2:
return 1;
}
这在clang上编译失败了!尽管这可能与具有
[[fallthrough]]
的编译器错误有关,但这让我开始研究标准。 相关标准附带了以下示例(请参见§VII):
鼓励实现为执行该情况进行优化(例如,在以下代码中a具有值1):
switch (a) {
case 1: [[likely]]
foo();
break;
//...
}
也就是说,属性在案例标签之后,而不是之前。
那么...到底是哪个呢?一开始,我期望标准是正确的,但那只是一个提议,不是真正的标准(据我所知,它可能已经被改变)。而且,我至少期望文档对基本语法是正确的——但它甚至无法编译。
[[likely]]
应用于foo();
和应用于case
语句之间的区别,因为(除了 fallthrough 或goto
之外),case
语句是唯一可以到达foo();
的方式。当然,我可以看到[[likely]] foo();
作为一个孤立的结构工作,但论文确实说这会影响case
。 - geometrian