mirror of
https://github.com/Light-City/CPlusPlusThings.git
synced 2026-10-29 11:24:07 +08:00
- 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
This commit is contained in:
78
site_extras/modern-cpp-cpp17-cpp-nodiscard.md
Normal file
78
site_extras/modern-cpp-cpp17-cpp-nodiscard.md
Normal file
@@ -0,0 +1,78 @@
|
||||
> 来自 [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
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user