引言
在阅读开源项目源代码是,发现了一个有趣且特殊的C++特性:属性。
属性(attribute specifier sequences)是在C++11标准引入的。在C++11之前,编译器特有的扩展被广泛用来提供额外的代码信息。例如,GNU编译器(GCC)使用__attribute__
来控制函数的行为。但是缺点也很明显,那就是这种方式缺乏标准化,不同编译器的特性并不兼容,严重影响了代码的可移植性。
为了解决这一问题,C++11标准引入了属性,提供一种标准化的方法来给编译器额外的信息。属性既可以应用于类型声明,也可以应用于声明语句、定义、代码块等,为编译器提供了关于编码意图的附加信息。
属性的作用
属性引入C++后,提供了以下几个方面的价值:
-
可移植性:提供了一种标准的方式来传达编译器特定的信息,减少了依赖特定编译器扩展的需要。
-
可读性:通过标准的属性,代码的特定行为和意图被清晰地表达,易于他人理解。
-
健壮性:属性可以帮助检测潜在的错误,如忽略了重要的函数返回值。
-
性能:许多属性可以帮助编译器进行优化,提高程序性能。
常见属性
以下是C++中一些常用的属性:
-
[[noreturn]]
- 表明函数不会返回到调用者。这通常用于那些通过抛出异常或终止程序来退出的函数。 -
[[nodiscard]]
- 用于函数或类型,标明调用者不应忽略返回值。对于类型,它表示该类型的对象或其构造函数返回的对象不应被忽略。 -
[[deprecated]]
- 标记某个实体(如函数、类、类型别名、变量等)为过时的,建议不要使用。可选地,可以提供一条消息说明替代的使用方式。 -
[[fallthrough]]
- 在C++17中引入,用于switch语句的case节中,明确表示允许控制流从当前case分支无条件跳转到下一个case分支的行为,避免编译器生成可能的警告。 -
[[maybe_unused]]
- 表示某个实体(如函数、类、变量等)可能不会被使用,从而防止编译器发出未使用警告。 -
[[likely]]
和[[unlikely]]
- 这两个属性是在C++20中引入的,用来显式地指示给定的布尔表达式结果的可能性。[[likely]]
表示表达式结果为true的可能性更高,而[[unlikely]]
表示结果为false的可能性更高。 -
[[no_unique_address]]
- 在C++20中引入,它指示类成员不必拥有唯一的地址,允许空基优化或类似的优化技术。
这些属性可以用来改善代码的文档化、提高性能、帮助编译器检查错误和警告,以及启用或禁用特定的编译器行为。
它们是现代C++编程中代码质量和维护方面的重要工具。不同的编译器可能对属性的支持程度有所不同。
常用属性示例
[[noreturn]]
[[noreturn]]
属性指示某个函数不会返回到调用者。这通常用于那些通过抛出异常或终止程序来退出的函数。
[[noreturn]] void terminate_program() {
// ... 清理操作 ...
std::exit(1); // std::exit不返回
}
[[nodiscard]]
[[nodiscard]]
属性用于函数或类型,标明调用者不应忽略返回值。这有助于防止编码中的错误,例如忘记处理函数返回的错误代码。
[[nodiscard]] int compute() {
// ... 计算操作 ...
return result;
}
void example()