我遇到了一个代码,其中使用了std::forward
。我已经用Google搜索了很长时间,并且无法理解它的真实目的和用途。
我在stackoverflow中看到了类似的线程,但仍然不清楚。有人可以用一个简单的例子来解释它吗?
PS:我已经完成了这个page,但仍然无法理解它的使用。请不要将此问题标记为重复,而是尝试帮助我。答案 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::string
或const 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&&
的类型为wrapper
。 std::forward
允许注入 T
的实际类型,T
,T&
,const T&
或T&&
,到通话网站。
答案 3 :(得分:0)
它的基本用途是你在函数g
中被调用如下:
g(T1 p1, T2 p2, /* ... */);
并且您想要使用完全相同的类型调用函数f
:
f(T1 p1, T2 p2, /* ... */);