我有一个关于转发推荐信的具体问题。(我认为)我理解R值引用和std::move
,但理解转发引用有困难:
#include <iostream>
#include <utility>
template <typename T> class TD; // from "Effective Modern C++"
void consume(const int &i) { std::cout << "lvalue\n"; }
void consume(int &&i) { std::cout << "rvalue\n"; }
template <typename T>
void foo(T&& x) {
// TD<decltype(x)> xType; - prints int&&
consume(x);
}
int main() {
foo(1 + 2);
}
t
是int
,这很好。如果x
是int&
类型,为什么它打印“lvalue”,而我们需要std::forward
?我的意思是,从int&&
到const int&
的转换在哪里?
呼叫:
consume(x);
将始终选择consumer()
的lvalue引用重载,因为表达式x
是一个lvalue。这与x
的推导类型无关。
但是,通过调用consumer()
作为:
consume(std::forward<T>(x));
如果传递给foo()
(即包装函数)的参数的值类别是一个rvalue,它将选择rvalue引用重载-即,它将该值类别传播到嵌套调用。
类型和值类别是两个独立的东西。x
的类型是int&
,但x
是变量的名称,x
是一个lvalue表达式,它不能绑定到int&
(但可以绑定到const int&
)。
以下表达式是lvalue表达式:
std::forward
用于根据转发引用参数的原始值类别将操作数转换为rvalue或lvalue。这意味着,当lvalueint
传递给foo
时,t
被推导为int&
,那么std::forward
将是lvalue表达式;当rvalueint
传递给foo
时,t
被推导为int
,那么std::forward
将是rvalue表达式。因此std::forward
可用于保留原始转发引用参数的值类别。