void g(int);
int f(int n) {
if (n > 5) [[unlikely]] { // n > 5 маловероятная ветка
g(0);
return n * 2 + 1;
}
switch (n) {
case 1:
g(1);
[[fallthrough]];
[[likely]] case 2: // n == 2 более вероятное значение
g(2); // нежели любое другое n
break;
}
return 3;
}
属性允许您为各种语言结构指定附加信息,例如类型、变量、名称、块和翻译单元。特别是,编译器可以使用此信息来生成更高效的代码,并在特定代码段级别向用户提供(反之亦然,抑制)警告消息,而不是整个程序或编译文件,如所提供的那样通过编译开关。
属性出现在c++11中,此后有所扩展。当前存在以下标准属性:
carries_dependency
deprecated
fallthrough
likely
和unlikely
maybe_unused
nodiscard
noreturn
no_unique_address
编译器的每个特定实现都可以扩展属性集,在这种情况下,将单独描述其行为。未知属性将被忽略,但可能会显示一条警告消息。
该属性始终用双方括号括起来:
让我们按顺序进行:
[[carries_dependency]]
此属性不会改变程序的含义,但可能会导致更高效的代码生成。该属性既可以应用于整个函数,也可以应用于它的参数。当在计算线程之间传递值时,它在具有弱有序体系结构的系统上很有用。最难理解的属性 :) 因此,有关enSO的更多信息。
[[deprecated]]
允许您将实体标记为已弃用或不安全,但仍允许使用。可以应用于类声明、typedef 名称、变量、非静态数据成员、函数、命名空间、枚举、枚举成员或模板特化。该属性可以提供一个由字符串文字给出的参数。例如:
当显示适当的警报时,文本消息将用作提示。
[[fallthrough]]
此属性适用于空操作,即
;
. 它只能在内部switch
用于通知编译器关于程序员设想的从一个分支case
到另一个分支的动作链的“失败”。case
如果在标签之间找不到语句,该属性允许您禁止编译器警告它可能发出的警告break
。通常,缺席break
可能是由于注意力不集中而引起的平庸错误。例子:[[likely]]
和[[unlikely]]
可以将属性添加到标签
case
或语句(statement )中,以向编译器暗示一段特定的代码在程序执行时预计最有可能(likely),或者相反,不太可能(unlikely )。例子:[[maybe_unused]]
用于通知编译器某个实体可能不会在程序中使用,并且应该抑制相应的警告。可以应用于类声明、typedef 名称、变量、非静态数据成员、函数、命名空间、枚举或枚举成员。如果您有在发布模式下构建时不会包含在二进制文件中的调试代码,则该属性会很有用。例子:
以前,您必须使用强制转换
void
来抑制可能的警告。[[nodiscard]]
表示从函数返回时必须使用结果。它既可以应用于类型(当声明类或枚举时),也可以直接应用于函数的返回类型。例子:
将结果显式转换为
void
覆盖属性的效果:或者,可以使用赋值
std::ignore
:从 C++20 开始,您可以使用可选的字符串文字来解释属性存在的原因,类似于 attribute
[[deprecated]]
。[[noreturn]]
表示该函数不返回控制权。可以应用于函数声明。与通过抛出异常、执行永恒循环或中断整个程序的执行来结束其工作的函数相关。例子:
如果标有该属性的函数
[[noreturn]]
返回对其中一个执行分支的控制,则会导致未定义的行为。[[no_unique_address]]
表示该类的非静态数据成员是一个可能重叠的子对象(不能应用于位域)。这意味着一个成员可以与这个或基类的另一个非静态数据成员共享一个地址,通常插入到对象末尾的占位符可以用来存储其他成员。例子:
这里
hasher
,pred
和alloc
可以具有相同的地址,就buckets
好像它们对应的类型为空一样。