第3.13章: attribute

English

什么是属性

属性(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++ 标准定义了一组不断增长的标准属性。下面是其中最重要的 几个的汇总。完整细节见:

cppreference.com:C++ 属性

C++11

  • [[noreturn]] —— 函数永不返回
  • [[carries_dependency]] —— 内存序依赖提示(C++26 中移除)
  • [[deprecated]]
  • [[deprecated("reason")]]
  • [[fallthrough]] —— 有意的 switch 贯穿
  • [[maybe_unused]] —— 抑制未使用警告
  • [[nodiscard]] —— 忽略返回值时发出警告
  • [[nodiscard("reason")]]
  • [[likely]] —— 分支预测提示
  • [[unlikely]] —— 分支预测提示
  • [[no_unique_address]] —— 允许成员存储重叠
  • [[assume(expression)]] —— 编译器可假定该表达式为真
  • [[indeterminate]] —— 对象具有不确定值
  • 语句上的属性

    有些属性直接作用于语句。最常见的是 [[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++ 标准。 完整列表:

    Clang 属性参考

    关于属性的警告

    属性只是提示,不是保证。

    要点