在c ++中使用std :: forward

时间:2013-09-04 16:19:25

标签: c++ c++11 std

我遇到了一个代码,其中使用了std::forward。我已经用Google搜索了很长时间,并且无法理解它的真实目的和用途。

我在stackoverflow中看到了类似的线程,但仍然不清楚。有人可以用一个简单的例子来解释它吗?

PS:我已经完成了这个page,但仍然无法理解它的使用。请不要将此问题标记为重复,而是尝试帮助我。

4 个答案:

答案 0 :(得分:4)

当你链接的页面构成它时:

  

这是一个帮助函数,可以完美地转发参数   作为rvalue引用推导出的类型,保留任何潜力   移动语义。

指定值时,如

void f1(int& namedValue){
    ...
}

void f2(int&& namedValue){
    ...
}

评估,无论如何,评估为lvalue

又一步。假设你有一个模板函数

template <typename T>
void f(T&& namedValue){
    ...
}

这样的函数可以用左值或右值调用;但是,无论如何,namedValue 评估为lvalue

现在假设您有两个辅助函数重载

void helper(int& i){
    ...
}
void helper(int&& i){
    ...
}

helper

中调用f
template <typename T>
void f(T&& namedValue){
    helper(namedValue);
}

将永远调用helper的第一个重载,因为namedValue是,一个命名值,当然,评估为{{1} }

为了在适当的时候调用第二个版本(即,当使用rvalue参数调用lvalue时),你写

f

所有这些都在以下

的文档中非常简明扼要地表达出来
  

对此功能的需求源于所有命名值的事实   (例如函数参数)总是评估为左值(即使是那些   声明为右值参考),这给我们带来了困难   在前进的模板函数上保留潜在的移动语义   其他函数的参数。

答案 1 :(得分:2)

每个表达式恰好是以下两个值类别之一:左值或右值。

通常情况下,如果您调用类似的函数:

template<typename T>
void f(T t);

template<typename T>
void g(T t)
{
    f(t);
}

g的参数的值类别在调用g和f之间丢失,因为命名参数(如局部变量)总是左值。

使用std::forward并将参数调整为使用参考折叠的“通用参考”,您可以保留值类别:

template<typename T>
void f(T&& t);

template<typename T>
void g(T&& t)
{
    f(forward<T>(t));
}

这就是为什么它被称为“前进”,因为你正在“转发”价值类别,而不是失去它。

因此,在示例中,如果使用rvalue调用g,则将使用rvalue调用f,而不是左值。

答案 2 :(得分:1)

它用于在将模板传递给另一个函数时保留模板中参数的确切类型。例如:

template<class T>
void wrapper(T&& arg)
{
    foo(std::forward<T>(arg)); // Forward a single argument.
}

其工作原理如下:

  • 如果函数wrapper获得std::stringconst std::string&,则会调用foo,就像arg的类型为const std::string&一样}。

  • 如果函数wrapper获得std::string&,则会调用foo,因为arg的类型为std::string&

  • 如果函数wrapper获得std::string&&,则会调用foo,因为arg的类型为std::string&&

std::forward解决的问题是,即使我们将arg传递给std::string,通常规则中函数内std::string&&的类型为wrapperstd::forward允许注入 T的实际类型,TT&const T&T&& ,到通话网站。

答案 3 :(得分:0)

它的基本用途是你在函数g中被调用如下:

g(T1 p1, T2 p2, /* ... */);

并且您想要使用完全相同的类型调用函数f

f(T1 p1, T2 p2, /* ... */);