前言:C++11是继98/03版本之后的大改版,其中增加了许多新特性,得到广泛的应用。这篇文章就介绍其中的右值引用。希望能够解释明白以下三个问题:
  1.什么是右值引用?
  2.右值引用有什么好处?
  3.右值引用的使用说明

1.什么是右值引用

  首先介绍下左右值(我发现自己学了好长时间都没有对两者进行区分~)
  对于左值、右值可以简单的以放在等号左右为区分,等号左边的是左值,等号右边的是右值。
  再来详细的介绍下各自的特点:
    左值:
    1)左值可以取地址
    2)左值可以修改
    3)左值可以放在等号左右两边
    右值:
    1)右值不可以取地址
    2)右值不可以直接修改
    3)右值只能放在等号右边
    4)右值往往是没有名称的

  再来举几个实例:
  左值举例:int a; int a = 3;
  上面的a都是左值

  关于右值,C++11将右值分了两类:纯右值、将亡值。从例子上看:
  1)纯右值 int a = 3; 就是指等号右边的常数,上式中的3
  2)将亡值其实就是中间变量的过渡,过渡之后就消亡,可以细分两种
   (1)函数的临时返回值 int a = f(3); f(3)的返回值是右值,副本拷贝给a,然后消失
   (2)表达式 像(x+y),其中(x+y)是右值

  在左右值使用时有三个原则,不能违反原则,否则编译无法通过:
  原则1:右值可以赋给左值,左值不能给右值(左值权限更大)

int a = 3;  // a是左值,3是右值
int d = a;  // d和a都是左值,左值可以赋给左值
int &&d = a; × // 右值引用左值不行
int &&d = 10;  // 右值引用右值可以
int &&d = f(10);  // 右值引用右值可以

  原则2:右值无法修改

int a = 10;  // 10是右值常数,无法修改

  原则3:编译器允许为左值建立引用,不可以为右值建立引用

int num = 10;
int &b = num;  √  // num是左值,可以左值建立引用
int &b = 10; ×  // 10是右值,不可以右值建立引用

  有一个问题存在:只有左值可以修改,那如果想对右值进行修改怎么办? 解决办法就是——右值引用

  右值引用的语法:&&
  使用右值引用需要注意三个问题:
  1)右值引用必须要进行初始化

int && a;  × // 必须初始化

  2)不能使用左值进行初始化

int num = 10;
int && a = num; × //不能使用左值进行右值初始化
int && a = 10; √

  3)右值引用可以对右值进行修改

int &&a = 10;    // 这里的a是右值引用,其实是10
a = 100;

  可以发现当对右值加上应用后可以修改值也可以修改地址,从功能上升为左值。所以有一种说法:右值引用的本质就是不用拷贝的左值

2.右值引用的好处?

  先想想引用的目的,传递参数有两种方式:值传递和引用传递。二者相比引用传递的优势就是通过传递地址,来减少一次拷贝。在常规写程序的时候,使用的都是左值引用。左值引用有两个使用场景:函数传参、函数返回值。
  1)函数传参:int f(int &a);
  2)函数返回值:int& f();
  以上两种情况使用的都是引用传递相比于值传递减少了拷贝次数。但有一种情况会出问题:就是返回值是一个临时对象。如下代码:

A& f() {A a;return a;
}

  当返回对象a的地址时,其实a作为在栈上的临时对象,作用域已经到了,被析构。这样如果外界再对这个地址进行访问时,就会出现问题。这也左值引用的一个弊端,而右值引用的出现就是为了解决这个问题。那右值引用是怎么解决返回的临时变量析构? 当返回值为右值引用时,会把返回的临时变量中的内存居为己用,仍保持了有效性,也避免了拷贝

3.右值引用的应用

  右值引用的应用场景场景主要有两个:移动语义、完美转发。下面分别介绍一下:
  移动语义
  如果我们把赋值这类操作看作资源转移,那么传统的资源转让是通过拷贝实现的,需要两份空间。而移动语义是通过移动来实现资源转让,只使用一个空间。来看一下移动语义的实现原理:
  首先明确移动语义和右值引用的关系:实现移动语义,就必须使用右值引用。移动语义具体实现是基于移动构造移动赋值,而移动构造函数和移动赋值函数都需要形参为右值引用类型。
  移动构造和移动赋值负责在不发生拷贝的情况下将资源转移到目标对象名下,
  ps:这里的构造和赋值一般指对象初始化的两种方式:

// 移动构造
Obj a(b);// 移动赋值
Obj a = b;

  移动语义避免了拷贝的风险,拷贝有两方面,一方面避免了浅拷贝可能引发的悬空指针的问题,另一方面也避免了深拷贝昂贵的开销

  前面说移动语义只能用右值引用实现,那有的时候就是希望用左值怎么办呢?这里有一个move函数,作用是把左值强制转换成右值引用,然后就能继续使用右值引用的特性。一般move用于对象,因为只有对象才会有各种构造函数,对于基本类型就无效啦。

  完美转发
  存在这样一种情况:

void notPerfectForward(int &&i) {printValue(i);  i会被当作左值处理
}

  这个转发过程中,i最开始是右值引用,但再次传递时却变成了左值。失去了右值引用的特性,不是我们的预期。这种情况适合使用完美转发。
  完美转发指函数模板可以将自己的参数完美地转发给内部调用的其他函数。完美指不仅能准确转发参数的值,还能保证转发参数的左右值属性不变。简单点说也就是如果参数是左值引用,转发给下一个函数还是左值引用;如果参数是右值引用,则转发给下一个函数还是右值引用。
  完美转发的实现基于,std::forward,像下面这样:

template<typename T>
void PerfectForward(T &&i) {printValue(std::forward<T>(i)); 这个i会被当作右值处理
}

  右值引用提供了很好的特性,这篇文章只是简单的对右值引用一些常见的概念做了解释,但想要具体使用还远远不够,只有在项目中多多使用,才能融会贯通,加油哇~

C++11特性——右值引用相关推荐

  1. C++11 标准新特性: 右值引用与转移语义(点评)

    <<C++11 标准新特性: 右值引用与转移语义>> 原文地址如下 http://www.ibm.com/developerworks/cn/aix/library/1307_ ...

  2. C++11:右值引用、移动构造、std::move, 以及使用emplace_back代替push_back

    最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 1.右值 ...

  3. C++11:右值引用、move, 以及使用emplace_back代替push_back

    最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 1.右值 ...

  4. std::move C++11 标准新特性: 右值引用与转移语义

    新特性的目的 右值引用 (Rvalue Referene) 是 C++ 新标准 (C++11, 11 代表 2011 年 ) 中引入的新特性 , 它实现了转移语义 (Move Sementics) 和 ...

  5. C++11 标准新特性: 右值引用与转移语义

    原文地址 http://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/ C++ 的新标准 C++11 已经发布一段时间了.本文介绍了新 ...

  6. C++ C++11新特性--右值引用

    左值与右值 在C语言中,左值和右值一般有两种区分的方法.可以出现在赋值符号"="的两边的值为左值,只能出现在赋值符号"="的右边的值为右值:还有一种说法是能取地 ...

  7. 【转】C++11 标准新特性: 右值引用与转移语义

    VS2013出来了,对于C++来说,最大的改变莫过于对于C++11新特性的支持,在网上搜了一下C++11的介绍,发现这篇文章非常不错,分享给大家同时自己作为存档. 原文地址:http://www.ib ...

  8. C++11新特性 右值引用与移动语义

    右值引用作用是可以减少内存拷贝次数,从而优化性能. 首先,什么是右值?右值是一个与左值相区分的概念.左值是:既能出现在等号左边也能出现在等号右边的变量或表达式,比如int a = 5,那么a就是一个左 ...

  9. 【 C++11 】右值引用和移动语义

    目录 1.基本概念 左值 vs 左值引用 右值 vs 右值引用 左值引用 vs 右值引用 2.右值引用使用场景和意义 左值引用的使用场景 左值引用的短板 右值引用和移动语义 ①.移动构造 ②.移动赋值 ...

最新文章

  1. [BZOJ2796][Poi2012]Fibonacci Representation
  2. 新疆兵团开展迎新春“送文化下基层”慰问演出活动
  3. AJAX 一些常用方法
  4. vs2015上使用github进行版本控制
  5. python特征选择relieff图像特征优选_ReliefF与QPSO结合的故障特征选择算法
  6. 获得北大新材料学院夏令营offer的艰险历程(附面试答辩PPT)
  7. boost::safe_numerics::safe_signed_range相关的测试程序
  8. python面向对象-4类的继承与方法的重载
  9. tab栏切换 动画的相关方法上 动画的相关方法下 隐藏动画案例 隐藏动画练习
  10. JS OOP -01 面向对象的基础
  11. 强悍的 vim —— g s 替换区别
  12. 最常见的Java框架有哪些?
  13. IoC、DI、AOP
  14. js日历控件源代码下载
  15. 凤凰项目-----读书笔记
  16. PPT视频无法播放,编解码器不可用
  17. OA 系统中的流程管理
  18. Linux 发展史小览
  19. 字节跳动资深面试官亲述:面试应该注意哪些问题?
  20. mysql基本50题_mysql-50题

热门文章

  1. 基于手工登记的被动访客系统
  2. markdown 换行_Markdown编辑神器-Typora
  3. k8s安装dashboard组件
  4. 怎么打开.war格式的文件
  5. [iOS]设备型号判断大全(包括iPhoneX)
  6. linux电源管理子系统,电源管理子系统
  7. OSChina 周四乱弹 —— 你的车我很喜欢,谢谢司机
  8. 信号(2)信号处理器函数
  9. linux控制cache使用值e,[轉]Linux塊設備加速緩存bcache和dm-cache:使用SSD來加速服務器...
  10. HTML标记【表格的控制】!