C++ 17 新增Attribute

C++ 17 新增Attribute

Attribute 可以理解成“附加给编译器看的标注信息”。C++17 在这方面新增了几个很常用的属性:[[nodiscard]][[maybe_unused]][[fallthrough]]。它们不会改变程序核心逻辑,但能帮助编译器给出更合理的诊断。

1. 什么是 Attribute?

它的基本写法是:

1
[[attribute_name]]

这类标记通常用于告诉编译器:

  • 这个返回值最好别忽略
  • 这个变量没用是有意为之
  • 这个 switchcase 故意不写 break

所以它更偏向代码语义提示和静态检查增强

2. [[nodiscard]]

这个属性的作用是:提醒调用者不要忽略返回值。

示例

1
2
3
4
5
6
7
8
9
10
[[nodiscard]] int getValue()
{
return 42;
}

int main()
{
getValue();
return 0;
}

上面这种调用方式,编译器通常会给出“返回值被忽略”的警告。

适合场景

  • 错误码返回
  • 资源申请结果
  • 状态判断函数

例如:

1
2
3
4
[[nodiscard]] bool openFile()
{
return false;
}

这种函数如果被直接忽略,很多时候确实是不太合理的。

3. [[maybe_unused]]

这个属性表示:这个变量、参数、函数可能暂时不会被使用,这是有意的。

示例

1
2
3
void func([[maybe_unused]] int value)
{
}

或者:

1
2
3
4
5
int main()
{
[[maybe_unused]] int ret = 10;
return 0;
}

这样可以减少“未使用变量”这类警告。

适合场景

  • 调试阶段临时变量
  • 条件编译下部分参数暂时不用
  • 保留接口兼容性时的占位参数

4. [[fallthrough]]

这个属性用于 switch 语句中,表示:当前 case 没写 break 是故意的,允许继续落入下一个 case。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

int main()
{
int value = 1;

switch (value) {
case 1:
cout << "case 1" << endl;
[[fallthrough]];
case 2:
cout << "case 2" << endl;
break;
}

return 0;
}

如果没有这个标记,很多编译器会提醒你“可能遗漏了 break”。

5. 这几个 Attribute 的价值

5.1 提高代码意图表达

有些代码即使不加属性也能运行,但加上以后别人一眼就能看出你的设计意图。

5.2 改善编译器诊断

很多时候这些属性本质上是在和编译器“沟通”,让告警更准确。

5.3 比注释更稳定

注释只是给人看,Attribute 是编译器真正能理解的结构化信息。

6. 使用时的注意点

6.1 它们主要是“提示”,不是强制逻辑

比如 [[nodiscard]] 通常会触发警告,而不是绝对编译错误。
具体效果还得看编译器和告警级别。

6.2 不要滥用

如果所有函数都加 [[nodiscard]],那它的信号价值反而会下降。
应当优先加在真正“不该被忽略”的返回值上。

6.3 可读性仍然优先

Attribute 是辅助信息,不能替代清晰的命名和合理的接口设计。

总结

C++17 新增的这几个 Attribute 都不复杂,但很实用。
[[nodiscard]] 适合保护关键返回值,[[maybe_unused]] 用来压制有意义的未使用警告,[[fallthrough]] 则让 switch 里的意图更明确。
它们属于那种“不加也能写代码,但加上会更舒服”的现代 C++ 小工具。