c++ - std::forward 与 std::move 的用法

标签 c++ c++11 move forward

我总是读到 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);
  • 42int 类型的右值.
  • T推导出为 int .
  • 调用 bar因此使用 int作为 std::forward 的模板参数.
  • std::forward<U> 的返回类型是 U && (在这种情况下,这是 int && )所以 t作为右值转发。

现在,我们调用 foo像这样:

int i = 42;
foo(i);
  • iint 类型的左值.
  • 由于完美转发的特殊规则,当 V 类型的左值用于推导TT && 类型的参数中, 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/

相关文章:

c++ - C++ 对象没有得到 std::moved 吗?

c++ - 有没有一种方法可以机械地识别哪些操作对移出的对象是安全的?

c++ - GTK 滚动窗口 - 将滚动条保持在底部

c++ - 为什么旧的小部件没有被删除?

c++ - 引用枚举时 C++ 2003 和 C++ 2011 之间代码不兼容的原因

c++ - 从函数返回时的右值引用行为

c++ - 在cpp中找出图像中对象的尺寸

C++ - 访问动态数组中的值

c++ - B.Stroustrup 新书中的优化与多线程

Java move 具有特定文件扩展名的文件