我正在审查这样的一些代码,其中A是可移动类型:

// Returns true exactly when ownership of a is taken
bool MaybeConsume(A&& a) {
  if (some condition) {
    Consume(std::move(a));  // ???
    return true;
  }
  return false;
}

// ... elsewhere ...

A a;
if (!MaybeConsume(std::move(a))) {
  a.DoSomething();  // !!!
}

我们的静态分析工具提示a在移动后被使用(位于!!!)。 IIUC std::move只是static_cast,在调用move构造函数或赋值运算符之前(大概在a中),对象Consume实际上不会被破坏。假设MaybeConsume满足注释中的契约(Contract),
  • 这样行吗?
  • 是UB吗?
  • std::move上的???是禁止操作吗?

  • (也许可以重构此特定实例以避免其细微之处,但我仍然想问一下我自己的理解)。

    最佳答案

    这是您的静态分析工具发出的虚假警告。



    是的,MaybeConsume正在执行注释中的内容。仅当some condition为true时,它才拥有其参数的所有权(假设Consume实际上确实从其参数移走了构造/赋值)。

    std::move 确实只是一个花哨的static_cast<T&&>,因此MaybeConsume(std::move(a))不会转移所有权,您只需将引用绑定(bind)到MaybeConsume的参数即可。



    不,如果a表示已假定拥有其参数,则您不会使用MaybeConsume



    好吧,这是一个空操作,因为它只是一个static_cast,但是如果您要问的是是否不必要,那么就不行了。在MaybeConsume主体内,a是左值because it has a name。如果Consume的签名是void Consume(A&&),则没有该std::move的代码将无法编译。

    从显示的示例用法来看,似乎不应该使用prvalue参数调用MaybeConsume,因为如果函数返回false,则调用者可能应该以其他方式使用该参数。如果是这样,则应将其签名更改为bool MaybeConsume(A&)。这可能会使您的静态分析工具感到高兴,因为这将使您可以编写if (!MaybeConsume(a))

    09-06 14:47