我正在审查这样的一些代码,其中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),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))
。