C++中的[[nodiscard]]属性有什么用?C++17避免API误用技巧【代码质量】

[[nodiscard]]是C++17引入的属性,用于标记函数返回值不应被忽略,否则编译器将警告;适用于资源管理、状态返回、工厂函数等场景,可防资源泄漏等低级错误。

[[nodiscard]] 是 C++17 引入的属性,用来告诉编译器:这个函数的返回值**不应该被忽略**。一旦调用者没用到它的返回值,编译器就会发出警告(甚至错误,取决于编译选项)。

它解决什么问题?

很多函数的返回值携带关键信息——比如是否成功、分配的资源、转换后的对象、错误码等。但开发者有时会不小心写成:

// 忘记接收返回值,逻辑出错却无提示
std::unique_ptr create_int();
create_int(); // 资源悄悄析构,但没人知道!

这类误用不会报错,运行时才暴露问题,调试成本高。

怎么用?加在函数声明上就行

常见适用场景:

  • 返回资源管理对象(std::unique_ptrstd::optional、自定义 RAII 类)
  • 返回状态或结果(如 std::expected、自定义 error_code 类型)
  • 返回必须检查的布尔值(如 try_lock()pop(std::optional&)
  • 工厂函数、转换函数(如 std::string_view::substr()

实际例子对比

不加 [[nodiscard]]:

// 编译通过,但逻辑危险
[[nodiscard]] std::optional find_value(const std::vector& v, int x);
find_value(v, 42); // 没接返回值 → 警告!

加了之后,GCC/Clang/MSVC 都会报类似:

warning: ignoring return value of function declared with 'nodiscard' attribute

小技巧和注意事项

  • 可以加在函数返回类型前,也可以加在函数名后(推荐前者,更清晰)
  • 支持自定义类型:在类定义上加 [[nodiscard]] struct MyResult { ... };,所有返回该类型的函数自动受约束
  • 若确实要忽略,显式转为 void(void)func();static_cast(func());
  • 不是万能的:不能防止“用了但没正确检查”,只能防“完全不用”

基本上就这些。它是轻量但高效的防御性编程手段,花几秒加个属性,就能拦住一大类低级但致命的误用。