左值右值右值引用与move()forward()

Posted 舆马者的悲伤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了左值右值右值引用与move()forward()相关的知识,希望对你有一定的参考价值。

1、左值(lvalue):可以进行取地址(&)运算的是左值。或者有时候可以理解为 既能够出现在等号左边也能出现在等号右边的变量(或表达式)。

2、右值(rvalue):不可以进行取地址(&)运算的是右值。或者有时候可以理解为 只能出现在等号右边的变量(或表达式)。

  • 常见的右值有 字面量、函数返回的临时对象,匿名对象等。
  • 以上判断一个对象是左值还是右值并不完全正确。
const int c_a = 10;        //左值,但是不能被赋值,也就不能出现在 = 左边
//字符串字面值,可以取地址,是左值,但是也不能位于等号左边
&("我只左值");                //正确
//有时候右值是可以位于等号左边的
string s1, s2;
s1 + s2 = "它是右值但是能被赋值“;

 

3、右值引用(rvalue referrence):是C++11引入的一个新类型。右值有一下特性:

  • 可以直接绑定到右值。
  • 不能直接绑定到左值。
  • 本身是一个左值。可以进行 &运算。
  • 右值能被 const 类型的引用绑定。
  • 可以使用move()将左值绑定到右值引用上。
int a = 10;
int &b = a;    
int &&c = a * 10;       //右值引用直接绑定右值
const int &d = a * 20;    //右值引用绑定到const型引用
int &&e = a;          //错误。无法将右值引用绑定到左值 int *f = &e; //右值引用可以进行&运算 int &&g = move(a);     //使用move()将左值绑定到右值引用上
  • 可以使用move()将左值绑定到右值引用上。
  • move调用告诉编译器:我们有一个左值,但我们希望像一个右值一样处理它。我们必须认识到,调用move就意味着承诺:除了对rr1赋值或销毁它外,我们将不再使用它在调用move后,我们不能对移后源对象的值做任何假设。我们可以销毁一个移后源对象,也可以赋予它新值,但是不能使用一个移后源对象的值。

  • std::forward()。 函数原型:std::forward<T>(u) 有两个参数:T 与 u。当T为左值引用类型时,u将被转换为T类型的左值,否则u将被转换为T类型右值。如此定义std::forward是为了在使用右值引用参数的函数模板中解决参数的完美转发问题。
//forward
template<typename _Tp>  
  inline _Tp&&  
  forward(typename std::remove_reference<_Tp>::type& __t)   
  { return static_cast<_Tp&&>(__t); }  


int a = 10;
int &b = forward<int &>(a);    //返回左值引用
int &&c = forward<int &&>(a);   //返回右值引用
int &&d = forward<int>(a);     //返回右值引用

 

以上是关于左值右值右值引用与move()forward()的主要内容,如果未能解决你的问题,请参考以下文章

C++11 左值右值右值引用详解

[转]C++11 左值右值右值引用详解

左值右值

左值左值引用右值右值引用

C++左值左值引用右值右值引用

C++11:左值右值左值引用右值引用