命名空间
变体
操作

属性说明符序列 (自 C++11 起)

来自 cppreference.cn
< cpp‎ | 语言
 
 
C++ 语言
通用主题
流程控制
条件执行语句
if
迭代语句(循环)
for
range-for (C++11)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 在 C++11 中弃用*
noexcept 说明符 (C++11)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
表达式
替代表示
字面量
布尔 - 整数 - 浮点
字符 - 字符串 - nullptr (C++11)
用户定义 (C++11)
实用工具
属性 (C++11)
类型
typedef 声明
类型别名声明 (C++11)
转型
内存分配
类特有函数属性
虚函数
override 说明符 (C++11)  
final 说明符 (C++11)
explicit (C++11)
静态

特殊成员函数
模板
模板特化
参数包 (C++11)
杂项
 
 
属性
(C++23)
(C++11)(直到 C++26)
(C++14)
(C++17)
(C++26)
(C++20)
(C++17)
(C++17)
(C++11)
(C++20)
 

为类型、对象、代码等引入实现定义的属性。

目录

[编辑] 语法

[[ attribute-list ]] (自 C++11 起)
[[ using attribute-namespace : attribute-list ]] (自 C++17 起)

其中 attribute-list 是零个或多个 attribute 的逗号分隔序列(可能以省略号 ... 结尾,表示 参数包展开

identifier (1)
attribute-namespace :: identifier (2)
identifier ( argument-list (可选) ) (3)
attribute-namespace :: identifier ( argument-list (可选) ) (4)

其中 attribute-namespace 是一个 identifier,而 argument-list 是括号、方括号和大括号平衡的标记序列(balanced-token-seq)。

1) 简单属性,例如 [[noreturn]]
2) 带有命名空间的属性,例如 [[gnu::unused]]
3) 带有参数的属性,例如 [[deprecated("because")]]
4) 同时具有命名空间和参数列表的属性。

如果 using namespace: 出现在属性列表的开头,则属性列表中的其他属性都不能指定命名空间:using 中指定的命名空间适用于所有这些属性

[[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]]
[[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute
(自 C++17 起)

[编辑] 解释

属性为实现定义的语言扩展提供了统一的标准语法,例如 GNU 和 IBM 语言扩展 __attribute__((...))、Microsoft 扩展 __declspec() 等。

属性几乎可以在 C++ 程序的任何地方使用,并且可以应用于几乎所有事物:类型、变量、函数、名称、代码块、整个翻译单元,尽管每个特定的属性仅在实现允许的地方有效:[[expect_true]] 可能是一个只能与 if 一起使用的属性,而不能与类声明一起使用。[[omp::parallel()]] 可能是一个应用于代码块或 for 循环的属性,但不能应用于 int 类型等(请注意,这两个属性是虚构的示例,请参阅下文了解标准属性和一些非标准属性)。

在声明中,属性可以出现在整个声明之前和直接在声明实体的名称之后,在这种情况下,它们会被组合起来。在大多数其他情况下,属性应用于紧邻的前一个实体。

`alignas` 说明符是属性说明符序列的一部分,尽管它具有不同的语法。它可以出现在 `[[...]]` 属性出现的位置,并且可以与它们混合使用(前提是它在允许使用 alignas 的地方使用)。

两个连续的左方括号标记 (`[[`) 只能在引入属性说明符或在属性参数内部出现。

void f()
{
    int y[3];
    y[[] { return 0; }()] = 1;  // error
    int i [[cats::meow([[]])]]; // OK
}

除了下面列出的标准属性外,实现可能支持具有实现定义行为的任意非标准属性。所有实现未知的属性都将被忽略,而不会导致错误。(自 C++17 起)

没有 attribute-namespace 的属性和名称为 `std` 或 `std` 后跟一个或多个数字的 attribute-namespace 保留用于未来的标准化。也就是说,每个非标准属性都在实现提供的 attribute-namespace 中,例如 `[[gnu::may_alias]]`、`[[clang::trivial_abi]]` 和 `[[msvc::noop_dtor]]`。

(自 C++20 起)

[编辑] 标准属性

以下属性由 C++ 标准定义。

标准属性在语法上不能被忽略:它们不能包含语法错误,必须应用于正确的目标,并且参数中的实体必须是 ODR 使用。

标准属性在语义上也不能被忽略:移除特定标准属性的所有实例后的行为对于存在属性的原始程序来说仍然是符合标准的行为。

(C++11)
指示函数不返回
(属性说明符)[编辑]
(C++11)(在 C++26 中移除)
指示 release-consume std::memory_order 中的依赖链在函数内外传播
(属性说明符)[编辑]
[[deprecated]][[deprecated("reason")]]
(C++14)(C++14)
指示允许使用使用此属性声明的名称或实体,但不建议出于某些 reason 使用
(属性说明符)[编辑]
(C++17)
指示从前一个 case 标签的 fall through 是有意的,并且不应被发出 fall-through 警告的编译器诊断
(属性说明符)[编辑]
(C++17)
如果存在未使用的实体,则抑制编译器警告
(属性说明符)[编辑]
[[nodiscard]][[nodiscard("reason")]]
(C++17)(C++20)
鼓励编译器在返回值被丢弃时发出警告
(属性说明符)[编辑]
(C++20)(C++20)
指示编译器应针对语句的执行路径比任何其他执行路径或多或少可能的情况进行优化
(属性说明符)[编辑]
(C++20)
指示非静态数据成员不必具有与其类的所有其他非静态数据成员不同的地址
(属性说明符)[编辑]
[[assume(expression)]]
(C++23)
指定 表达式 在给定点始终求值为 true
(属性说明符)[编辑]
(C++26)
指定对象如果未初始化,则具有不确定值
(属性说明符)[编辑]
指示应针对从 同步语句 的调用优化函数定义
(属性说明符)[编辑]

[编辑] 注解

可以使用 __has_cpp_attribute 预处理器宏检查给定平台上是否存在每个单独的属性。

特性测试宏 Std 特性
__cpp_attributes 200809L (C++11) 属性
__cpp_namespace_attributes 201411L (C++17) 命名空间的属性

[编辑] 示例

[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
inline int f(); // declare f with four attributes
 
[[gnu::always_inline, gnu::const, gnu::hot, nodiscard]]
int f(); // same as above, but uses a single attr specifier that contains four attributes
 
// C++17:
[[using gnu : const, always_inline, hot]] [[nodiscard]]
int f[[gnu::always_inline]](); // an attribute may appear in multiple specifiers
 
int f() { return 0; }
 
int main() {}

[编辑] 缺陷报告

以下行为变更缺陷报告已追溯应用于先前发布的 C++ 标准。

DR 应用于 已发布行为 正确行为
CWG 2079 C++11 [[ 不能出现在属性参数内部 允许
CWG 2538 C++11 尚不清楚标准属性是否可以在语法上被忽略 禁止
CWG 2695 C++11 尚不清楚标准属性是否可以在语义上被忽略 禁止
P2156R1 C++11 每个标准属性都必须在 属性列表 中最多出现一次 不需要

[编辑] 参见

__has_cpp_attribute - 检查属性是否存在
C 文档属性说明符序列

[编辑] 外部链接

1.  GCC 中的属性。这些属性可以用作 [[gnu::...]]参见 SO
2.  Clang 中的属性.
3.  MSVC 中的属性.