我正在审查一些这样的代码,其中 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
满足评论中的约定,
- 这行得通吗?
- 是 UB 吗?
std::move
在???
是无操作吗?
(可能这个特定的实例可以重构以避免微妙,但我还是想问问自己的理解)。
最佳答案
这是来自您的静态分析工具的虚假警告。
- Does this work?
是的,MaybeConsume
正在做评论所说的。只有在 some condition
时,它才拥有其论点的所有权。为真(假设 Consume
实际上确实从其参数中移动了构造/赋值)。
std::move
确实只是看中static_cast<T&&>
所以MaybeConsume(std::move(a))
没有转让所有权,您只是绑定(bind)了对 MaybeConsume
的引用的参数。
- Is it UB?
不,你没有使用 a
如果 MaybeConsume
表明它已经承担了它的论点的所有权。
- 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/