C++11新特性属性(Attribute)的简单解析

C++11加入的属性(Attribute)是给各种语言扩展(例如GNUIBM的语言扩展 __attribute__((...))微软的语言扩展 __declspec() 等)提供了统一化的语法

属性可以运用在C++的几乎每个地方

  • 类型
  • 变量
  • 函数
  • 名字
  • 代码块
  • 整个翻译单元

C++目前引入的标准属性

  • C++11 起
    [[noreturn]] 指示函数不返回
    [[carries_dependency]] 指示释放消费 std::memory_order 中的依赖链传入和传出该函数
  • C++14 起
    [[deprecated]]
    [[deprecated(“原因”)]] 指示允许使用声明有此属性的名称或实体,但因原因 而不鼓励使用
  • C++17 起
    [[fallthrough]] 指示从前一 case 标号直落是有意的,而在发生直落时给出警告的编译器不应该为此诊断
    [[nodiscard]] 鼓励编译器在返回值被舍弃时发布警告
    [[maybe_unused]] 禁止显示有关未使用实体的警告
  • C++20 起
    [[likely]]
    [[unlikely]] 指示编译器应该针对通过某语句的执行路径比任何其他执行路径更可能或更不可能的情况进行优化
    [[no_unique_address]] 指示非静态数据成员的地址不需要拥有与它所在的类的所有其他非静态数据成员不同
    [[nodiscard(“原因”)]] 鼓励编译器在返回值被舍弃时发布警告
  • C++23 起
    [[assume]] 指出某个表达式在某个地方始终会求值为 true
    [[optimize_for_synchronized]] (TM TS) 指示应该针对来自 synchronized 语句的调用来优化该函数定义

语法

1
2
[[ 属性列表 ]]
[[ using 属性命名空间 : 属性列表 ]] // C++17开始

应用在函数上

1
2
[[deprecated("这个函数的实现不安全")]]
int foo();

应用在代码块上

1
2
3
4
5
6
#include <iostream>
int main() {
if (1 > 0) [[likely]] {
std::cout << "1>0";
}
}

标准属性

noreturn

它表明了执行后不返回到调用者
使用了这个属性的函数有 exit(),abort()

1
2
3
4
5
6
7
8
#include <iostream>
#include <stdexcept>
[[noreturn]] void ExitProgram() {
throw std::runtime_error("抛出错误"); // 抛出错误于是不会返回主函数
}
int main() {
ExitProgram();
}

deprecated

1
[[deprecated(Message)]]

表示拥有该属性的实体被弃用,允许被使用,但是不鼓励使用
编译器通常会对其使用情况发出警告若指定了字符串字面量(Message),则它通常被包含于警告中。

1
2
3
4
5
6
7
#include <stdexcept>

[[deprecated("会抛出异常")]] void ExitProgram() {
throw std::runtime_error("抛出错误");
}

int main() { ExitProgram(); }

编译输出

1
2
3
4
5
6
main.cpp:8:25: warning: ‘void ExitProgram()’ is deprecated: 会抛出异常 [-Wdeprecated-declarations]
8 | int main() { ExitProgram(); }
| ~~~~~~~~~~~^~
main.cpp:4:35: note: declared here
4 | [[deprecated("会抛出异常")]] void ExitProgram() {
| ^~~~~~~~~~~

多种使用方法

class/struct/union

1
class [[deprecated("这个类有新的实现可以代替")]] udp;

typedef/别名声明

1
2
[[deprecated("请使用标准的int32_t")]] typedef int32_t i32;
using i32 [[deprecated("请使用标准的int_32")]] = int32_t;

变量声明

1
2
3
4
5
[[deprecated]] int num;

class udp {
[[deprecated("新版本将不再基于文件描述符")]] int fd_;
};

命名空间

1
2
3
namespace [[deprecated("以后将剥离net命名空间")]] net {
class udp;
};

枚举/枚举项

1
2
3
4
enum [[deprecated("目前网络库并不完善")]] ip {
v4,
v6[[deprecated("目前对于ipv6的支持并不全面")]]
};

模板特化

1
2
template <typename type> struct MyStruct;
template <> struct [[deprecated("该类的实现有问题")]] MyStruct<int>;

nodiscard

可以增强代码的可读性和可维护性,从而提醒开发人员不要忽略返回的值
出现在函数声明、枚举声明或类声明中

1
2
3
[[nodiscard]] int foo() {
return 10;
}

编译输出

1
2
3
4
5
6
main.cpp:7:17: warning: ignoring return value of ‘int foo()’, declared with attribute ‘nodiscard’ [-Wunused-result]
7 | int main() { foo(); }
| ~~~^~
main.cpp:6:19: note: declared here
6 | [[nodiscard]] int foo() { return 10; }
| ^~~

struct

1
2
3
4
5
6
7
8
9
10
11
12
13
[[nodiscard]] struct MyStruct {
int value;
};

void foo() {
MyStruct myObject{42}; // 创建 MyStruct 对象
// 使用对象的值
}

int main() {
foo(); // 未使用 foo() 函数中 MyStruct 对象的返回值,编译器可能会发出警告
return 0;
}

该文章并未完全写完,我将会在几天后完善该文章