c++ - 对象传递给 std::move 但未从中移出?

标签 c++ c++11 undefined-behavior rvalue-reference

我正在审查一些这样的代码,其中 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,对象 a 直到调用移动构造函数或赋值运算符才真正被删除(大概在 Consume 中)。假设 MaybeConsume 满足评论中的约定,

  1. 这行得通吗?
  2. 是 UB 吗?
  3. std::move??? 是无操作吗?

(可能这个特定的实例可以重构以避免微妙,但我还是想问问自己的理解)。

最佳答案

这是来自您的静态分析工具的虚假警告。

  1. Does this work?

是的,MaybeConsume正在做评论所说的。只有在 some condition 时,它才拥有其论点的所有权。为真(假设 Consume 实际上确实从其参数中移动了构造/赋值)。

std::move 确实只是看中static_cast<T&&>所以MaybeConsume(std::move(a))没有转让所有权,您只是绑定(bind)了对 MaybeConsume 的引用的参数。

  1. Is it UB?

不,你没有使用 a如果 MaybeConsume表明它已经承担了它的论点的所有权。

  1. Is std::move at ??? a no-op?

嗯,这是一个空操作,因为它只是一个 static_cast ,但如果你想问它是否不必要,那么,不,它不是。在 MaybeConsume 的正文中, a是一个左值 because it has a name .如果Consume的签名是 void Consume(A&&) ,那么没有它,代码将无法编译 std::move .


从您展示的示例用法看来,您不应该调用 MaybeConsume使用纯右值参数,因为如果函数返回 false,调用者可能应该以其他方式使用参数.如果是这样,那么您应该将其签名更改为 bool MaybeConsume(A&) .这可能会让您的静态分析工具满意,因为这将允许您编写 if (!MaybeConsume(a)) .

关于c++ - 对象传递给 std::move 但未从中移出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48799984/

相关文章:

c - 为什么这段代码不返回垃圾值?

c++ - 如何使用 boost C++ 复制图形?

c++ - 在 C++ 的集合中查找方法的时间复杂度是多少?

c++ - 使用 decltype() 和 SFINAE 的错误

c - 为什么我的空字符数组以长度 6 开头?

c++ - if语句中定义的局部变量的行为异常

c++ - CMake:当输入列表的头文件部分更改与正在输出的对象无关时,是否可以重建目标?

c++ - 为什么我的 vector 大小一直重置为 0? (目前正在使用类(class))

c++ - 是否每个循环都会评估基于 C++11 范围的 for 循环条件?

c++ - STL 容器 : Constructor's Allocator parameter and scoped allocators