C++11之右值引用

 

----------------------------右值引用---------------------------------

 

右值定义:

  通俗来讲,赋值号左边的就是左值,赋值号右边的就是右值。可以取地址是左值,不可以取地址的是右值。C++11,之前没有明确提出右值的概念,所以 C++11 以前这些说活都是正确的。

  C++11 中的左值,仍然等同于 C++98 左值。C++11 中的右值,除了 C++98 中的右值以外,增加了将亡值的概念。 


  如下图

 

#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    int a; int & lref = a;
    //int && rref = a;   //!error:右值引用不能接受左值
    //int & elref = a*34; //!error:普通引用不能接受临时值
        const int &eclref = a*34;
    int && erref = a*34;
    return 0;
}

 

 

 

 const T & 万能常引用

   其本质也是产生了临时对象, 并且该临时对象是 const 的。 此对于非基本数据类型也适用, 但需要转化构造函数。 

 

class A
{
public:
  A(){
    cout<<"A() "<<this<<endl;
  }
  ~A(){
  cout<<"~A() "<<this<<endl;
  }
  A(const A &another)
  {
  cout<<"A(const A&)"<<&another<<"->"<<this<<endl;
  }
  void dis()
  {
    cout<<"xxxxoooooooooooo"<<endl;
  }
};


A getObjectA()
{
  return A();
}


int
main(int argc, char *argv[]) {   // int& ri = 5;   // const & cri = 5;   // float f = 34.5;   // int & irf = f;   // const int & cirf = f;   // A objA;   // int& irA = objA;   // const int& cirA = objA;   // cout<<cirA<<endl;   const A& ret = getObjectA();   ret.dis(); //!error:一个const对象,没有const函数,不能再完成调用。   return 0; }

  此种举措,也可以在返回中避免临时对象,再次拷贝和销毁。但时临时对象的性质是 const 的,也会给后续的使用带来不便。
 

 右值引用与左值引用的对比
1) 都属于引用类型。
2)都必须初始化。 左值引用是具名变量值的别名, 右值引用是匿名变量的别名。
3) 左值引用, 用于传参, 好处在于, 扩展对象的作用域。 则右值引用的作用就在于延长了临时对象的生命周期。
4)  避免“先拷贝再废弃” 带来的性能浪费。
5)  对将亡值进行引用的类型; 它存在的目的就是为了实现移动语义

 

 

 const T & 与T && 本质对比

#include <iostream>

using namespace std;

int main( )
{
  const int & i =10;
 int && iii = 10 }

/*
int && iii = 10的汇编代码
0x08048400  mov    $0xa,%eax
0x08048405  mov    %eax,-0xc(%ebp)
0x08048408  lea    -0xc(%ebp),%eax
0x0804840b  mov    %eax,-0x4(%ebp)

第一句将10赋值给eax,第二句将eax放入-0xc(%ebp)处,“临时变量会引用关联到右值时,右值被存储到特定位置”,-0xc(%ebp)便是该临时变量的地址,后两句通过eax将该地址存到iii处。

通过上述代码,我们还可以发现,在上述的程序中-0x4(%ebp)存放着右值引用iii,-0x8(%ebp)存放着左值引用,-0xc(%ebp)存放着10,而-0x10(%ebp)存放着1,左值引用和右值引用同int一样是四个字节(因为都是地址)

const int & i =10的汇编代码
0x08048583  mov    $0xa,%eax
0x08048588  mov    %eax,-0x8(%ebp)
0x0804858b  lea    -0x8(%ebp),%eax
0x0804858e  mov    %eax,-0x4(%ebp)

-0x4(%ebp)处存放着i,-0x8(%ebp)处则存放着临时对象10,程序将10的地址存放到了i处。看到这里会发现const引用在绑定右值时和右值引用并没有什么区别。

*/

参考:https://www.cnblogs.com/likaiming/p/9045642.html

 

 

 

重要的事情再说一遍:  

  总之读完该篇博文你只需要知道:右值引用存在的意义就在于它既获得了同const T&同样的效率,又解决了const引用不可作为non-const类型使用的问题!

  想要更深入的了解右值引用以及他的作用:请参考另一篇博文:https://www.cnblogs.com/wangkeqin/p/9338358.html



 

 

 

 

 

 

 

 

posted @ 2018-07-15 13:23  小念之歌  阅读(536)  评论(0编辑  收藏  举报