属性列表
属性(attribute)是 C++ 提供给编译器和工具的额外语义提示。它通常不改变代码的核心逻辑,而是让编译器检查得更早、优化得更明确,或让接口意图更清楚。
属性属于现代 C++ 的高阶知识:日常开发不需要大量使用,但读库代码、写公共接口和做静态检查时很有价值。
1. 基本语法
[[attribute]] void f();
[[attribute(args)]] int g();属性可以放在函数、类型、变量、枚举、语句等位置,具体能放哪里取决于属性本身。
2. 常用标准属性
| 属性 | 标准 | 主要作用 | 常见场景 |
|---|---|---|---|
[[nodiscard]] | C++17 / C++20 扩展 | 提醒返回值不能随意忽略 | 错误码、结果对象、工厂函数 |
[[maybe_unused]] | C++17 | 标记可能未使用,避免无意义警告 | 调试变量、平台条件编译参数 |
[[deprecated]] | C++14 | 标记接口已废弃 | 旧 API 迁移 |
[[fallthrough]] | C++17 | 明确 switch 分支有意贯穿 | case 之间不写 break |
[[likely]] / [[unlikely]] | C++20 | 提示分支概率 | 性能敏感路径 |
[[no_unique_address]] | C++20 | 允许空成员不占额外空间 | 泛型库、压缩空对象 |
3. [[nodiscard]]
[[nodiscard]] 用来提醒调用者:返回值表达了重要结果,忽略它很可能是错误。
[[nodiscard]] bool save_config(const Config& cfg);
void run(const Config& cfg) {
save_config(cfg); // 编译器通常会警告:返回值被忽略
}适合使用的情况:
- 函数返回成功/失败状态。
- 函数返回错误码或结果对象。
- 工厂函数返回需要接管的对象。
- 返回值被忽略后可能导致资源泄漏、逻辑错误或错误处理缺失。
C++20 起也可以标记类型:
struct [[nodiscard]] Result {
bool ok;
std::string message;
};
Result parse(std::string_view text);如果确实要忽略返回值,用显式 (void) 表达意图:
(void)save_config(cfg);4. 使用原则
- 属性是辅助约束,不替代清晰的类型设计和错误处理。
- 公共接口优先考虑
[[nodiscard]]、[[deprecated]]这类能减少误用的属性。 - 性能提示类属性要谨慎使用,先确认瓶颈,再给编译器提示。
- 编译器对属性的警告强度可能不同,重要项目应配合编译选项和 CI 检查。
5. 总结
属性列表不是必背语法表。学习重点是知道:现代 C++ 可以用标准属性把“这个返回值很重要”“这个接口废弃了”“这里故意贯穿”等意图交给编译器检查。[[nodiscard]] 只是属性体系里的一个常用子集。