意义:可以避免无谓的复制,提高程序的性能。

左值:表达式结束后依然存在的持久化对象
右值:表达式结束后不再存在的临时对象

所有的具名变量和对象都是左值,而右值不具名。
区分左值和右值的快捷方法:
看能不能对表达式取地址,如果能则是左值,否则就是右值。

右值分为纯右值和将亡值。
纯右值是C++98中的右值概念,如非引用函数返回的临时变量;
一些运算表达式,如4+6产生的临时变量;不和对象关联的字面量值,
如10,‘s’,true,“hello”等这些不能被取地址的值。

将亡值:c++11中新增的和右值引用相关的表达式,这样的表达式通常是将要移动的对象
T&&函数返回值,std::move()函数的返回值等。
将亡值和纯右值统一看成右值,不影响使用。

c++98中引用很常见,就是给变量取一个别名,在c++11中,因为增加了右值引用的概念,
所以c++98中的引用都称为左值引用。

int a = 10;
int &refA = a;
int &b = 1;   //编译错误,1是右值,不能使用左值引用

c++11中的右值引用使用&&符号,如

int &&a = 1;
int b = 1;
int &&c = b;  //编译错误,不能将左值赋值给一个右值引用
class A
{
public:int a;
};
A getTemp()
{return A();
}
A &&a = getTemp();  //getTemp()返回值是右值(临时变量)

getTemp()返回的右值本来在表达式语句结束后,其生命也就该终结了(临时变量),而通过
右值引用,该右值又获得了新生,其生命周期与右值引用类型变量a的生命一样,只要a活着,该
右值临时变量将会一直存活下去,实际上就是给临时变量去了一个名字。

a的类型为右值引用类型(int &&),如果从左值和右值的角度区分它,它实际上是一个左值。
因为可以对它取地址,而且它还有名字,是一个已经命名的右值。

所以,左值引用只能绑定左值,右值引用只能绑定右值。常量左值引用是个特例,它可以算一个
万能的引用类型,可以绑定非常量左值,常量左值,右值,而且在绑定右值的时候,可以像右值引用一样
将右值的生命期延长,缺点是只能读不能改。例子如下:

const int &a = 1;  //常量左值引用绑定右值,不会报错
class A
{
public:int a;
};
A getTemp()
{return A();
}
const A &a =getTemp();   //不会报错,而A& a会报错

实际上,我们在很多情况下都使用了常量左值引用这个功能,例子如下:

class Copyable
{
public:Copyable() {}Copyable(const Copyable &o){std::cout << "Copied" << std::endl;}
};Copyable ReturnRvalue()
{return Copyable(); //返回一个临时对象
}void AcceptVal(Copyable a)
{
}
void AcceptRef(const Copyable &a)
{
}int main()
{std::cout<<"pass by value"<<std::endl;AcceptVal(ReturnRvalue());  //应该调用2次拷贝构造函数std::cout<<"pass by reference"<<std::endl;AcceptRef(ReturnRvalue());  //应该只调用一次拷贝构造函数
}

上述例子运行之后,结果和预想的不一样。AcceptVal(ReturnRvalue())需要调用两次拷贝构造函数,一次在ReturnRvalue()函数中,构造一个Copyable()对象,返回的时候会调用拷贝构造函数生成一个临时对象。在调用AcceptVal()时,会将这个对象拷贝给函数的局部对象a,一共调用了两次拷贝构造函数。而AcceptRef()的不同之处在于形参是常量左值引用,它能接收一个右值,而不需要拷贝。

实际的结果是,不管哪种方式,一次拷贝构造函数都没有调用。

这是因为编译器开启了返回值优化(RVO/NRVO,RVO,Return Value Optimization返回值优化;NRVO,Nameed Return Valude Optimization)。编译器发现ReturnRvalue内部生成了一个对象,返回之后还需要生成一个临时对象调用拷贝构造函数,很麻烦,所以直接优化成一个对象,避免拷贝,而这个临时变量又被赋值给了函数的形参,还是没必要,这3个变量都用一个变量代替了,不需要调用拷贝构造函数。

为了能够更好的观测结果,可以在编译的时候加上-fno-elide-constructors选项(关闭返回值优化),此时结果和预想的一样。上述的例子是想说明常量左值可以绑定一个右值,可以减少一次拷贝(使用非常量左值引用会使失败,因为ReturnRvalue()返回的是临时对象(右值))。

//g++ test.cpp -o test -fno-elide-constructors

总结:T是一个具体类型

(1)左值引用,使用T&,只能绑定左值

(2)右值引用,使用T&&,只能绑定右值

(3)常量左值,使用conts T&,可以绑定左值和右值。

(4)已命名的右值引用,编译器会认为是左值。

(5)编译器有返回值优化功能,但不可过于依赖。

参考:https://www.jianshu.com/p/d19fc8447eaa

C++ 右值引用与左值引用相关推荐

  1. 2020-09-22C++学习笔记之引用1(1.引用(普通引用)2.引用做函数参数 3.引用的意义 4.引用本质5.引用结论 6.函数返回值是引用(引用当左值)7测试代码)

    2020-09-22C++学习笔记之引用1(1.引用(普通引用)2.引用做函数参数 3.引用的意义 4.引用本质5.引用结论 6.函数返回值是引用(引用当左值)7测试代码) 1.引用(普通引用) 变量 ...

  2. C++中“非常量引用的初始值必须是左值”的处理方法

    原文:https://blog.csdn.net/hou09tian/article/details/80565343 1 左值和右值 在C++中,左值可以出现在赋值语句的左边和右边:右值只能出现在赋 ...

  3. 左值、左值表达式、左值引用 C++

    左值和右值 1.左值:左值是一个对象或变量,可以代表着一个固定地址. int i = 3://此时,i是个变量,本质和对象一样,是一块内存区域,代表着一个固定的地址. 右值:不能作为左值的都是右值,要 ...

  4. 的引用_左值、右值、左值引用、右值引用

    [导读]:本文主要详细介绍了左值.右值.左值引用.右值引用以及move.完美转发. 左值和右值 左值(left-values),缩写:lvalues 右值(right-values),缩写:rvalu ...

  5. 非常量引用的初始值必须是左值_C++核心编程--引用

    2 引用 2.1 引用的基本使用 作用: 给变量起别名 语法: 数据类型 &别名 = 原名 示例: int main() {int a = 10;int &b = a;cout < ...

  6. java中的左值右值_利用左值右值实现树状结构

    image.png 1. 查询 1.1. 得到节点 Node 下的所有节点,并按树状排序 SELECT * FROM tree WHERE lft BETWEEN Node.Lft AND Node. ...

  7. C++/C++11中左值、左值引用、右值、右值引用的使用

    C++的表达式要不然是右值(rvalue),要不然就是左值(lvalue).这两个名词是从C语言继承过来的,原本是为了帮助记忆:左值可以位于赋值语句的左侧,右值则不能. 在C++语言中,二者的区别就没 ...

  8. 39.左值、左值引用、右值、右值引用

    1.左值和右值的概念 左值是可以放在赋值号左边可以被赋值的值:左值必须要在内存中有实体:          右值当在赋值号右边取出值赋给其他变量的值:右值可以在内存也可以在CPU寄存器.       ...

  9. 左值、右值、左值引用、右值引用

    1. 左值 左值(lvalue,left value),顾名思义就是赋值符号左边的值,可以取地址.准确来说,左值是表达式(不一定是赋值表达式)后依然存在的持久对象. 可以将左值看作是一个关联了名称的内 ...

最新文章

  1. tf.contrib.layers.xavier_initializer
  2. ubuntu 配置网络
  3. NYOJ 73 比大小
  4. mysql 共享锁和排他锁 意向锁 记录锁 Gap Locks Next-Key Locks 插入意向锁介绍
  5. 【倍增】【线段树】雨林跳跃(luogu 7599[APIO 2021 T2])
  6. ES6的Promise -- 逻辑执行的顺序
  7. Qt5 程序启动画面图片效果
  8. 便携式CAN分析仪与毫米波雷达搭配使用
  9. 机器视觉Halcon教程(1.介绍)
  10. php自学多久可以上岗,自学php多久能找工作,PHP要自学多久才能找到工作
  11. 【APT】The following signatures were invalid
  12. 使用 mesh 实现多边形裁剪图片!Cocos Creator!
  13. 爆款“小黄鸭”之后,实在RPA助力电商人双11提销量
  14. 东华助手 v1.6.5
  15. 关于个人如何接入微信支付接口,适用于h5,小程序等应用场景
  16. 【GDOI2018模拟7.14】小奇的糖果
  17. 计算机重启后桌面文件全部丢失,蓝屏后桌面文件丢失,电脑蓝屏桌面文件丢失...
  18. linux 修改主机名 命令,Linux修改主机名命令详解
  19. PieLove(鹊桥·征男友女友) 版-内容抓取程序
  20. 【UE4 C++】如何关联GitHub 下载UE4引擎源代码

热门文章

  1. GDAL坐标转换——TransformPoint
  2. *1.设计一个异常类表示对负数求平方根的错误,在类Test的main方法中,* 从键盘中输入一个数字,若输入的数不小于0,则输出该数的平方根(用Math.sprt());* 若小于0,则抛出自定义
  3. Windows系统的消息机制
  4. maven下载(国内镜像)
  5. 华为2016校园招聘上机笔试题
  6. 如何在分割后保留分隔符?
  7. Centos 安装 OpenLDAP
  8. 哈尔滨傲澜智伴机器人_通辽智伴机器人,智伴机器人招商,傲澜智伴机器人
  9. flask 下载文件
  10. ios沙箱软件_iOS沙盒管理工具FHHSandBoxViewer