【问题标题】:Why is std::move not [[nodiscard]] in C++20?为什么 C++20 中的 std::move 不是 [[nodiscard]]?
【发布时间】:2020-08-06 06:27:33
【问题描述】:

我最近阅读了 C++17 中的 [[nodiscard]],据我了解,这是一个新功能(按合同设计?),它迫使您使用返回值。这对于像 std::launder (自 C++20 以来没有丢弃)这样的有争议的函数是有意义的,但我想知道为什么 std::move 在 C++17/20 中没有像这样定义。你知道一个很好的理由还是因为 C++20 还没有最终确定?

【问题讨论】:

  • 因为当您不使用它时,绝对不会发生任何坏事(或根本不会发生)。
  • @SebastianRedl:同样,没有任何有用的事情发生。这与编写空语句相同,因此[[nodiscard]] 将有助于诊断错误。此外,当 vector::empty() 被忽略时,也不会发生任何不好的事情,但出于显而易见的原因,它会被标记为 [[nodiscard]]
  • @SebastianRedl 这听起来是一个很好的理由标记它[[nodiscard]]:“嘿,你做了一些完全没有意义的事情。你是不是打算做其他事情?”跨度>
  • @bbalchev std::move 不动。通过std::move 传递一个对象并忽略结果绝对没有任何作用。
  • @bbalchev 所有std::move 所做的只是返回一个对对象的右值引用;以便对象 可以 随后从 if 以这种方式使用引用移动。

标签: c++ c++17 language-lawyer c++20 nodiscard


【解决方案1】:

自 VS 2017 15.6 以来,MSVC 标准库团队继续添加了数千个 [[nodiscard]] 实例,并报告说它取得了巨大的成功(在发现大量错误和没有产生用户投诉方面)。他们描述的标准大约是:

  1. 纯观察者,例如vector::size()vector::empty,甚至std::count_if()
  2. 获取原始资源的事物,例如allocate()
  3. 丢弃返回值极有可能导致错误代码的函数,例如std::remove()

MSVC 确实按照这些标准将std::move()std::forward() 标记为[[nodiscard]]

虽然它没有在标准中正式注释,但它似乎为用户提供了明确的好处,而且更多的是制作这样的论文来标记所有正确的东西[[nodiscard]](同样,来自 MSVC 的数千个实例)和应用它们——这本身并不复杂,但量很大。与此同时,也许可以刺激你最喜欢的标准库供应商并要求他们[[nodiscard]] 很多东西?

【讨论】:

    【解决方案2】:

    AFAIK P0600R1 是将[[nodiscard]] 添加到应用于 C++20 的标准库的唯一提议。从那篇论文:

    我们建议采用保守的方法:

    [...]

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

    • [...]
    • 不使用返回值是没有意义的,但不会造成伤害,通常不是错误
    • [...]

    因此,如果出现这种情况,[[nodiscard]] 不应发出错误代码

    • [...]
    • 没有伤害,可能没有任何状态变化意味着不会发生

    所以原因是标准库使用了保守的方法,还没有提出更激进的方法。

    【讨论】:

    • 我不知道。不使用 std::move 的返回值在我的书中始终是一个错误,因此根据您的引用应该是 nodiscard :它要么意味着用户忘记使用返回值,要么调用是不必要的,因为它有没有效果。
    • @KonradRudolph:显然没有人向委员会展示过std::move() 上缺少 nodiscard 导致实际错误的常见情况。考虑在 C++ 标准讨论邮件列表中提出这个问题。
    • @einpoklum 大概和其他人一样,我认为这个问题不够紧迫,不会浪费委员会的时间(已经有太多新提案了)。我要说的是,缺少[[nodiscard]]可能是一种疏忽,而不是出于此答案中的引用而有意识的决定。
    猜你喜欢
    • 2021-01-13
    • 2014-02-16
    • 2020-10-01
    • 2021-05-07
    • 1970-01-01
    • 2021-05-24
    • 2020-10-29
    相关资源
    最近更新 更多