void g(int&& a ) {
int i = 0;
int &&ri = a; //编译错误,等价于 int &&ri = (a) 无法将一个右值引用绑定到另一个左值引用上。
// int &&rri = std::move(a); std::move 返回一个匿名右值引用
}
void g(int &&) {
cout << "right reference" << endl;
}
void g(const int&) {
cout << "left reference" << endl;
}
void f(int&& a ) {
/* do something*/
g(a); //g ( (std::move(a)) ) 同会调用右值引用版本, 因为 ( std::move(a) ) 不属于单个变量表达式,也返回了一个匿名右值引用.
/* do something*/
}
对于 void f(int && arg), 试图把右值引用 arg 绑定到另一个右值引用 a 上, 然而在绑定时 a 被当成单个变量表达式从而得到的类型是 int&, 从而 f 调用的是 void g (int & arg)。在进行右值绑定时,凡是有名字的都必然是左值/左值引用, 所以为了使用 g (int &&) 我们必须显式的造出一个匿名的右值引用来。f 一定要写成 void f (T&&), 首先最最基本的要求就是, 传递给 g 的参数不是 f 拷贝后的参数, 而是 f 收到的参数,所以一定要是引用,绝对不能是拷贝,至于写成右值引用的形式, 是为了接受右值。不管 f 接受到的是左值还是左值引用,最后 T 都会变成 左值引用并且不影响 g 的接受, 不管接受的是右值还是匿名右值引用(上面提到具名右值引用,会在绑定时当成表达式而变成左值引用,int &&a; 是具名右值引用, std::move(a) 则得到一个匿名右值引用, 4 + 3 这样的得到的是右值), 最终都会被std::forward变成匿名右值引用被 g 正确接受。