【问题标题】:Is nodiscard necessary on operators?运营商是否需要nodiscard?
【发布时间】:2020-11-22 00:18:28
【问题描述】:

[[nodiscard]] 属性对操作符是必需的吗?或者假设编译器会像对大多数可疑丢弃的东西一样发出警告是否安全?

例如一个重载的operator+,应该应用该属性吗?诸如函数转换运算符或新运算符之类的特殊运算符呢?什么时候学究气了?

【问题讨论】:

  • 取决于调用代码来调用这些运算符函数而不使用它们返回的内容是否有意义。例如,在二进制operator+() 的情况下,与some_result = a + b 相比,a + b 形式的语句(不使用operator+() 返回的任何内容)是否有意义?如果它对您的课程没有意义,您可能希望将[[nodiscard]] 属性添加到operator+()
  • 从来没有必要
  • @Peter 在我的情况下,我不会重载运算符,因为它的运行方式与原语的运行方式不同。换句话说,operator+ 永远不应该被丢弃。也就是说,我几乎看不到任何使用 nodiscard 属性的代码,我想知道这是因为它默认为 on。
  • @lajoh90686 - 您认为该课程的用户多久会使用一次operator+() 并丢弃结果?是否存在这样做的显着(但这是为您的程序指定的)缺点的情况?如果答案是“不经常”和“否”——我认为这在实践中很常见——那么这些运营商被标记为[[nodiscard]]
  • 如果丢弃结果不是错误,请不要使用[[nodiscard]]。当[[nodiscard]] 有用时,很好的例子是operator newstd::asyncoperator+ 看起来不太适合 [[nodiscard]]。推荐阅读:N.Josuttis. [[nodiscard]] in the library.

标签: c++ c++17 nodiscard


【解决方案1】:

让我引用以下 N.Josuttis 的论文:“[[nodiscard]] in the library”(有一些遗漏,请参阅全文):

C++17 引入了[[nodiscard]] 属性。问题是,现在在标准库中的何处应用它。应在以下位置添加:

  • 不使用返回值总是一个“巨大的错误”(例如,总是导致资源泄漏),
  • 不使用返回值会带来麻烦,而且很容易发生(不明显有问题)。

在以下情况下不应该添加:

  • 至少对于某些输入,不使用返回值是一种可能/常见的编程方式,
  • 不使用返回值没有任何意义,但不会造成伤害,通常不会出错。

所以,[[nodiscard]] 不应该在这种情况下发出错误代码

  • 不使用返回值会很有用,
  • 通常不使用返回值,
  • 没有伤害,可能没有状态变化意味着不会发生。

【讨论】:

  • 很好的参考。我正在搜索核心指南,但仅在演员表的上下文中提及(以消除警告)
【解决方案2】:

从来没有必要添加[[nodiscard]] 属性。来自cppreference

如果声明为 nodiscard 的函数或返回枚举的函数或按值声明为 nodiscard 的类被丢弃值表达式调用而不是强制转换为 void,则鼓励编译器发出警告。

请注意最后一部分:“...鼓励编译器发出警告。”就标准而言,不能保证实际上会有警告。它是一个实施质量问题。如果您的编译器确实发出了警告(阅读文档)并且您将此类警告视为错误,那么 [[nodiscard]] 可能会很有用。

在操作符上使用该属性是迂腐的,而丢弃返回只是潜在的错误。我只会在调用运算符时使用它并且丢弃结果总是一个逻辑错误。许多运算符仅使用返回值来启用链接,而[[nodiscard]] 宁愿成为此类运算符的烦恼。在某些情况下,决定并不那么明显,这取决于您的意见和风格。

【讨论】:

  • 所以像 iostream 的 operator<< 这样的东西不会有它,但是像矢量类 operator+ 这样的东西应该?
  • @lajoh90686 取决于向量类上的operator+ 的作用。对于operator<<,它将完全没用,因为您总是丢弃返回的值(至少是链接中的最后一次调用,例如std::cout << "hello" << " world";
  • 笛卡尔向量中的向量类。像一个坐标。
  • @lajoh90686 这真的取决于细节。 operator+ 通常是 const 并且确实返回一个新实例,即调用它并丢弃结果是不正确的。然而,操作符可以被重载来做一些奇怪的事情。 operator+ 可以是非const 并修改this,例如它可以计算一个向量添加到另一个向量的频率,在这种情况下,即使您丢弃结果,调用运算符也会产生影响
【解决方案3】:

运营商需要nodiscard吗?

没有。 nodiscard 和其他属性是可选的。

或者假设编译器会像对大多数可疑丢弃的东西一样发出警告是否安全?

除非程序格式错误,否则无法保证语言中的任何警告。

我也不会假设没有 nodiscard 的警告,因为在很多情况下操作结果被故意丢弃。一个常见的例子:

a = b;  // result of assignment was discarded

事实上,如果所有丢弃的结果都导致警告,那么 nodiscard 属性就没有任何用途。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    相关资源
    最近更新 更多