Files
CPlusPlusThings/site_extras/modern-cpp-cpp17-cpp-nodiscard.md
light-city dfe1c933b3 docs: address community issue feedback (#5 #338 #142 #246 #136 #303)
- const README: rewrite the space-saving claim per issue #5 follow-ups
  (constant-expression const vs #define immediates; which const qualify
  as constant expressions)
- const README: fix the class-section diagnosis per issue #338 (overload
  resolution picks the const overload; the restriction only surfaces
  once that overload is removed)
- sizeof README: virtual-inheritance result is compiler-dependent
  (GCC merges vbptr+vfptr -> 16, MSVC keeps them separate -> 32) #246
- static README: new section on internal linkage / access restriction
  with anonymous-namespace comparison #142
- 10-day practice: full problem list table + fixed day links #136
- new design_pattern/singleton/singleton_default.hpp: reusable
  thread-safe CRTP singleton template, compile+concurrency tested #303
2026-10-13 19:23:54 +08:00

78 lines
2.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> 来自 [C++那些事网站](https://light-city.github.io/stories_things/modern-cpp/cpp17/cpp-nodiscard/) 的文章,由站点同步脚本导出。
# C++17 [[nodiscard]] 属性
自C++17引入[[nodiscard]]属性以来,我们在编写API时有了一种更强大的工具,用于标记那些在调用时不应该被忽略的函数返回值。在本文中,我们将深入探讨[[nodiscard]]的用法,并注意一些潜在的陷阱。
## 什么是[[nodiscard]]?
[[nodiscard]]是一种函数属性,它告诉编译器函数的返回值不应该被忽略。这在那些依赖于返回值的函数中尤为有用,例如谓词函数或工厂函数。
## 如何使用[[nodiscard]]?
在类、构造函数以及枚举上使用[[nodiscard]]都是可能的。下面是一些示例:
```cpp
class [[nodiscard]] A {};
class B {
public:
[[nodiscard]] B() = default;
};
enum class [[nodiscard]] State {
Default,
Foo,
Bar
};
```
在上述例子中,编译器将在返回值被忽略时发出警告,有助于我们及早发现潜在的bug。
## 警惕:[[nodiscard]]的陷阱
尽管[[nodiscard]]可以有效地防止返回值被无意中忽略,但我们需要注意一些潜在的陷阱。一个常见的陷阱是使用[[nodiscard]]的函数返回一个类似于作用域守卫的对象,以在作用域结束时执行清理操作(比如提交事务)。
```cpp
[[nodiscard]] ScopeGuard createScopeGuard() {
// Implementation of a scope guard
}
// 在这里,用户可以选择忽略返回值,导致作用域立即销毁,从而失去清理效果
std::ignore = createScopeGuard();
```
尽管[[nodiscard]]表明函数返回值不应该被忽略,但用户仍然可以通过`std::ignore`等手段明确地忽略返回值,从而绕过清理操作。
## 完整示例
```cpp
#include <tuple> // std::ignore
class [[nodiscard]] A {};
class B {
public:
[[nodiscard]] bool isOk() const { return true; }
};
// no need for nodiscard, A is nodiscard
A foo() {
return A();
}
// B is not nodiscard, mark it explicitly
[[nodiscard]] B bar() {
return B();
}
int main()
{
foo(); // warning: ignoring temporary created by a constructor declared with 'nodiscard' attribute
bar(); // warning
std::ignore = foo(); // ok
auto b = bar(); // ok
b.isOk(); // warning
if (b.isOk()) {} // ok
}
```