C++ 右值

  • 左值和右值: (i) 是一个表达式, 对于只有单个变量的表达式,c++编译器的处理是返回一个绑定到该变量的左值引用,所以decltype((i)) 返回 int&。右值绑定时会把所有的 单个变量 都看成变量表达式, 然而单个变量的表达式返回的是一个左值引用。而右值引用无法绑定到左值引用。局部变量i不可作为非类型模板参数, 非类型模板参数必须在编译时即为常量表达式。模板实参推断中才会出现引用折叠。只有发生类型推导的时候,T&&才表示万能引用;否则,表示右值引用。
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 正确接受。
发布了75 篇原创文章 · 获赞 6 · 访问量 2800

猜你喜欢

转载自blog.csdn.net/u014618114/article/details/103540100