我一直在观看Scott Meyers在C++ and Beyond 2012会议上的通用引用演讲,到目前为止一切都很清晰。然而,在大约50分钟左右,一个观众提出了一个问题,这也是我想知道的。Meyers说他不关心答案,因为这是非成语化的,会让他感到愚蠢,但我仍然很感兴趣。
所呈现的代码如下:
重点在于当我们使用rvalue引用时,我们知道它是一个rvalue,因此应该使用std::move来保留它是一个rvalue的事实。当我们使用通用引用(T&&,其中T是一个推导类型)时,我们希望std::forward保留它可能是一个lvalue或rvalue的事实。
那么问题是:既然std::forward保留了传递到函数中的值是lvalue还是rvalue,而std::move只是将其参数转换为rvalue,我们是否可以在任何地方都使用std::forward?在所有需要使用std::move的情况下,std::forward是否会像std::move一样工作,还是有一些重要的行为差异被Meyers的概括忽略了?
我并不建议任何人这样做,因为正如Meyers正确地指出的那样,这完全不符合惯用法,但以下是否也是std::move的有效用法:
所呈现的代码如下:
// Typical function bodies with overloading:
void doWork(const Widget& param) // copy
{
// ops and exprs using param
}
void doWork(Widget&& param) // move
{
// ops and exprs using std::move(param)
}
// Typical function implementations with universal reference:
template <typename T>
void doWork(T&& param) // forward => copy and move
{
// ops and exprs using std::forward<T>(param)
}
重点在于当我们使用rvalue引用时,我们知道它是一个rvalue,因此应该使用std::move来保留它是一个rvalue的事实。当我们使用通用引用(T&&,其中T是一个推导类型)时,我们希望std::forward保留它可能是一个lvalue或rvalue的事实。
那么问题是:既然std::forward保留了传递到函数中的值是lvalue还是rvalue,而std::move只是将其参数转换为rvalue,我们是否可以在任何地方都使用std::forward?在所有需要使用std::move的情况下,std::forward是否会像std::move一样工作,还是有一些重要的行为差异被Meyers的概括忽略了?
我并不建议任何人这样做,因为正如Meyers正确地指出的那样,这完全不符合惯用法,但以下是否也是std::move的有效用法:
void doWork(Widget&& param) // move
{
// ops and exprs using std::forward<Widget>(param)
}
lvalue_expression
的类型是左值,则std::forward(lvalue_expression)
将返回一个左值;如果lvalue_expression
的类型是右值(例如命名的右值),则将返回一个右值。在这里,我正在对一个我知道具有右值类型的表达式使用std::forward
。 - Joseph Mansfieldstd::forward
的整个意义在于它有时可以将左值转换为右值。 - Mankarse