ste*_*sic 23 c++ undefined-behavior rvalue-reference c++11
我正在审查一些像这样的代码,其中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(); // !!!
}
Run Code Online (Sandbox Code Playgroud)
我们的静态分析工具抱怨a在移动(at !!!)后使用.IIUC std::move只是一个static_cast,并且在调用a移动构造函数或赋值运算符(可能是在Consume)之前,该对象实际上不会被删除.假设MaybeConsume在评论中满足合同,
std::move在???无操作?(可能这个特殊的实例可以重构以避免微妙,但我仍然想要求我自己的理解).
Pra*_*ian 14
这是静态分析工具的虚假警告.
- 这有用吗?
是的,MaybeConsume正在做评论所说的.当它some condition为真时,它只接受其参数的所有权(假设Consume实际上确实从其参数移动了构造/赋值).
std::move确实只是一种幻想,static_cast<T&&>所以MaybeConsume(std::move(a))不转移所有权,你只是绑定对MaybeConsume参数的引用.
- 是UB吗?
不,你没有利用aif MaybeConsume表明它已经承担了其论证的所有权.
- 是
std::move在??? 没有操作?
嗯,这是一个无操作,因为它只是一个static_cast,但如果你想问这是否是不必要的,那么,不,它不是.在体内MaybeConsume,a是一个左值,因为它有一个名字.如果签名Consume是void Consume(A&&),那么代码将不会编译std::move.
根据您显示的示例用法,似乎您不应该MaybeConsume使用prvalue参数调用,因为如果函数返回,调用者应该以某种其他方式使用该参数false.如果这是真的,那么你应该将其签名更改为bool MaybeConsume(A&).这可能会使您的静态分析工具感到高兴,因为这样可以让您编写if (!MaybeConsume(a)).