我总是读到 std::forward
仅用于模板参数。然而,我在问自己为什么。请参阅以下示例:
void ImageView::setImage(const Image& image){
_image = image;
}
void ImageView::setImage(Image&& image){
_image = std::move(image);
}
这是两个基本相同的功能;一个采用左值引用,另一个采用右值引用。现在,我想既然 std::forward
应该返回一个左值引用,如果参数是一个左值引用和一个右值引用,如果参数是一个,这个代码可能是简化成这样:
void ImageView::setImage(Image&& image){
_image = std::forward(image);
}
这有点类似于 cplusplus.com 提到的 std::forward
示例(只是没有任何模板参数)。我只是想知道,这是否正确,如果不正确,为什么。
我也在问自己到底有什么不同
void ImageView::setImage(Image& image){
_image = std::forward(image);
}
最佳答案
你不能使用std::forward
没有明确指定其模板参数。它是有意在非推断上下文中使用的。
要理解这一点,您需要真正了解转发引用(T&&
用于推导出的 T
)在内部是如何工作的,而不是把它们当作“它的魔法”而挥之不去。那么让我们来看看。
template <class T>
void foo(T &&t)
{
bar(std::forward<T>(t));
}
假设我们调用 foo
像这样:
foo(42);
-
42
是int
类型的右值. -
T
推导出为int
. - 调用
bar
因此使用int
作为std::forward
的模板参数. std::forward<U>
的返回类型是U &&
(在这种情况下,这是int &&
)所以t
作为右值转发。
现在,我们调用 foo
像这样:
int i = 42;
foo(i);
-
i
是int
类型的左值. - 由于完美转发的特殊规则,当
V
类型的左值用于推导T
在T &&
类型的参数中,V &
用于扣减。因此,在我们的例子中,T
推导出为int &
.
因此,我们指定 int &
作为 std::forward
的模板参数.因此,它的返回类型将是“int & &&
”,它折叠为 int &
.这是一个左值,所以 i
作为左值转发。
总结
为什么这适用于模板是当你做 std::forward<T>
, T
有时是引用(当原件是左值时),有时不是(当原件是右值时)。 std::forward
因此将酌情转换为左值或右值引用。
您无法在非模板版本中进行这项工作,因为您只有一种类型可用。更不用说setImage(Image&& image)
根本不接受左值——左值不能绑定(bind)到右值引用。
关于c++ - std::forward 与 std::move 的用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28828159/