【发布时间】:2012-10-24 13:02:56
【问题描述】:
我一直在观看 Scott Meyers 在 C++ 和 Beyond 2012 会议上的talk on Universal References,到目前为止一切都很有意义。然而,一位观众在大约 50 分钟时提出了一个我也想知道的问题。 Meyers 说他不关心答案,因为它不习惯用语并且会让他觉得很傻,但我仍然感兴趣。
呈现的代码如下:
// 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)
}
关键是当我们获取一个右值引用时,我们知道我们有一个右值,所以我们应该std::move 它来保留它是一个右值的事实。当我们采用通用引用(T&&,其中T 是推导类型)时,我们希望std::forward 保留它可能是左值或右值的事实。
所以问题是:既然std::forward 保留了传递给函数的值是左值还是右值,而std::move 只是将其参数转换为右值,我们可以在任何地方都使用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)
}
【问题讨论】:
-
move(lvalue) 将参数转换为右值。 forward(lvalue) 将其保留为左值。
-
@AndrewTomazos-Fathomling
std::forward(lvalue_expression)如果lvalue_expression的类型是左值,它将给出一个左值,如果lvalue_expression的类型是右值,它将给出一个右值(在例如,命名的右值)。在这里,我在我知道具有右值类型的表达式上使用std::forward。 -
@Andrew Tomazos - Fathomling - 这是错误的,
std::forward的全部意义在于它有时可以将左值更改为右值。 -
这个术语有点含糊。当我说 forward(lvalue) 时,我的意思是一个通过引用折叠推导出类型 T& 的参数。
标签: c++ c++11 move-semantics rvalue-reference perfect-forwarding