第3.13章: attribute
什么是属性
属性(attribute)向编译器提供额外信息。它们不会 改变程序的含义,但可以启用警告、优化,或特殊行为。
属性使用以下语法:
[[attribute]]
属性是 C++ 语言的一部分,而不是宏。
基本语法
[[nodiscard]]
int compute();
你可以把属性应用于函数、变量、类型和语句。
多个属性
你可以在同一对括号中列出多个属性:
[[nodiscard, maybe_unused]]
int f();
也可以分开写:
[[nodiscard]]
[[maybe_unused]]
int f();
两种形式等价。
属性命名空间
标准属性隐式使用 std 命名空间:
[[nodiscard]]
[[maybe_unused]]
[[deprecated]]
厂商特有的属性使用显式命名空间:
[[gnu::always_inline]]
[[clang::fallthrough]]
[[msvc::noinline]]
命名空间可以防止不同编译器之间的冲突。
using 属性语法
C++ 还支持 using-attribute 语法,可以一次为多个属性 指定命名空间。
[[using CC: opt(1), debug]]
void f();
这等价于:
[[CC::opt(1), CC::debug]]
void f();
标准 C++ 属性(C++11 → C++26)
C++ 标准定义了一组不断增长的标准属性。下面是其中最重要的 几个的汇总。完整细节见:
C++11
语句上的属性
有些属性直接作用于语句。最常见的是
[[likely]] 与 [[unlikely]]。
正确的语法是把属性放在条件之后、 语句体之前:
if (x > 0) [[likely]] {
print("positive\n");
} else [[unlikely]] {
print("non-positive\n");
}
该属性作用于语句,而不是条件。
Clang 属性
Clang 支持大量额外属性,用于诊断、优化、ABI 控制、代码生成 等等。
示例:
[[clang::always_inline]]
[[clang::noinline]]
[[clang::reinitializes]]
[[clang::trivial_abi]]
Clang 提供的属性远多于 C++ 标准。 完整列表:
关于属性的警告
- 属性不会改变程序语义。
- 编译器可能忽略它不认识的属性。
- 不应当用属性来掩盖逻辑错误。
- 厂商属性会降低可移植性。
属性只是提示,不是保证。
要点
- 属性提供提示:它们不改变程序含义。
- 标准语法:
[[attribute]]。 - 多个属性:
[[a, b]]或多个方括号块。 - 命名空间:
gnu::、clang::、msvc::。 - using 属性语法:
[[using CC: opt(1), debug]]。 - 语句属性:
if (cond) [[likely]] { ... }。 - 标准属性:已在上文列出。
- Clang 提供更多属性:见 Clang 文档。