首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C++那些事之nodiscard

C++那些事之nodiscard

作者头像
公众号guangcity
发布2023-12-01 13:31:38
发布2023-12-01 13:31:38
1.2K0
举报
文章被收录于专栏:光城(guangcity)光城(guangcity)

C++那些事之nodiscard

自C++17引入[[nodiscard]]属性以来,我们在编写API时有了一种更强大的工具,用于标记那些在调用时不应该被忽略的函数返回值。在本文中,我们将深入探讨[[nodiscard]]的用法,并注意一些潜在的陷阱。

什么是[[nodiscard]]?

[[nodiscard]]是一种函数属性,它告诉编译器函数的返回值不应该被忽略。这在那些依赖于返回值的函数中尤为有用,例如谓词函数或工厂函数。

如何使用[[nodiscard]]?

在类、构造函数以及枚举上使用[[nodiscard]]都是可能的。下面是一些示例:

代码语言:javascript
复制
class [[nodiscard]] A {};

class B {
public:
    [[nodiscard]] B() = default;
};

enum class [[nodiscard]] State {
    Default,
    Foo,
    Bar
};

在上述例子中,编译器将在返回值被忽略时发出警告,有助于我们及早发现潜在的bug。

警惕:[[nodiscard]]的陷阱

尽管[[nodiscard]]可以有效地防止返回值被无意中忽略,但我们需要注意一些潜在的陷阱。一个常见的陷阱是使用[[nodiscard]]的函数返回一个类似于作用域scop guard的对象,以在作用域结束时执行清理操作(比如提交事务)。

代码语言:javascript
复制
[[nodiscard]] ScopeGuard createScopeGuard() {
    // Implementation of a scope guard
}

// 在这里,用户可以选择忽略返回值,导致作用域立即销毁,从而失去清理效果
std::ignore = createScopeGuard();

尽管[[nodiscard]]表明函数返回值不应该被忽略,但用户仍然可以通过std::ignore等手段明确地忽略返回值,从而绕过清理操作。

完整示例

代码语言:javascript
复制
#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
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-11-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++那些事之nodiscard
  • 什么是[[nodiscard]]?
  • 如何使用[[nodiscard]]?
  • 警惕:[[nodiscard]]的陷阱
  • 完整示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档