前言

为了了解C++11的新特性右值引用,不得不重新认识一下左右值。学习之初,最快的理解,莫过于望文生义了,右值那就是赋值号右边的值,左值就是赋值号左边的值。在中学的数学的学习中,我们理解的是,左值等价于等号左边的值,右值等价于等号右边的值;当我们继续学习C语言时,等号=不再叫等号,盖头换面叫做赋值号;那么来到C++我们还能这么理解吗?答案是部分否定的。

假如你现在还是这样理解,那么请继续往下......

C++中何为左值lvalue和右值rvalue?

左值lvalue:可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。在C语言中,左值最初指的是出现在赋值语句左边的实体,但这是引入const之前的情况。now,常规变量和const变量都可视为左值,因为可通过地址访问它们。常规变量属于可修改的左值,const变量属于不可修改的左值。左值基本上和以前的认知没有太大的改变。

右值rvalue:字面常量(用括号括起来的字符串除外,因为它们表示地址)、包含多项的表达式以及返回值的函数(条件是该函数返回的不是引用)。

简单的区别左值和右值:
右值就是一个临时变量(后面将详细的解释),只有临时地址空间,左值有其地址空间,换句话说,使用取地址符&对某个值取地址,如果不能得到地址,则是右值!

例如:

int a = 0;

cout << &a << endl; // ok! lvalue

cout << &404;  // error! rvalue

对于前面提到的右值的特性:

1) 允许调用成员函数。

2) 只能被 const reference 指向。

3) 右值不能当成左值使用,但左值可以当成右值使用

临时变量

仅当函数参数为const reference时,临时变量才能与之匹配。

什么时候将创建临时变量呢?
如果引用参数是const,则编译器将在下面两种情况下生成临时变量:
1. 实参的类型正确,但不是左值
2. 实参的类型不正确,但可以转换为正确的类型

Example:

double cube(const double &ra)
{
return ra * ra * ra;
} double side = 3.0;
double* pd = &side;
double& rd = side;
long edge = 5L;
double lens[] = {2.0, 5.0, 10.0, 12.0}; double c1 = cube(side);
double c2 = cube(lens[]);
double c3 = cube(rd);
double c4 = cube(*pd); double c5 = cube(edge); // ra是临时变量
double c6 = cube(7.0); // ra是临时变量
double c7 = cube(side + 4.0); // ra是临时变量

参数side、lens[2]、rd和*pd都是有名称的、double类型的数据对象,因此不需要借助临时变量,可以为其创建引用。
然而edge虽然有名称但是类型却不正确,正好符合产生临时变量的情况2 “实参的类型不正确,但可以转换为正确的类型” ,double引用不能指向long。参数7.0和side + 4.0的类型都正确,但是木有名称,属于右值。在这些情况下,编译器都会生成一个临时匿名变量,并让ra指向它。这些变量生命周期只在函数调用期间,此后编译器便会随意的删除。

为何临时变量 or 右值 对const引用的限制时合理的呢?

请看下面的例子:

void swapr(int& a, int& b)    // swapr()完成数的交换的功能
{
int temp; temp = a;
a = b;
b = temp;
} long a = , b = ;
swapr(a, b);

这里我们使用反证法,假设这个调用是木有错误的,那么这里的类型不匹配,因此编译器将创建两个int临时变量,将它们初始化为3和5,然后交换临时变量的内容,但是这只是交换了两个临时变量的值,a和 b并没有交换,这与swapr()函数完成的功能是相悖的。

总结来说,如果接受引用参数的函数的意图是修改作为参数传递的变量,则创建临时变量将阻止这种意图的实现。解决方法是,禁止创建临时变量。因此这个调用也是错误的。如果函数调用的参数是右值或与相应的const引用参数的类型不匹配,则C++将创建类型正确的匿名变量,将函数调用的参数的值传递给该匿名变量,并让参数来引用该变量

  

C++中让人忽视的左值和右值的更多相关文章

  1. C++中的左值与右值(二)

    以前以为自己把左值和右值已经弄清楚了,果然发现自己还是太年轻了,下面的这些东西是自己通过在网上拾人牙慧,加上自己的理解写的. 1. 2. 怎么区分左值和右值:知乎大神@顾露的回答. 3. 我们不能直接 ...

  2. c++中的左值与右值

    左值(lvalue)和右值(rvalue)是 c/c++ 中一个比较晦涩基础的概念,不少写了很久c/c++的人甚至没有听过这个名字,但这个概念到了 c++11 后却变得十分重要,它们是理解 move/ ...

  3. C++中的左值和右值

    左值和右值的定义 在C++中,能够放到赋值操作符=左边的是左值,能够放到赋值操作符右边的是右值.有些变量既能够当左值又能够当右值.进一步来讲,左值为Lvalue,事实上L代表Location,表示在内 ...

  4. C++中 左值和右值的区别

    总结: C++11中所有的值属于左值,右值两者之一. 左值引用:指的是可以放在赋值表达式左边的事物——在堆上或者栈上分配的命名对象或者其他对象成员——有明确的内存地址. 对左值的const引用创建临时 ...

  5. c++中的左值和右值的理解

    1.左值和右值的概念 C++中左值(lvalue)和右值(rvalue)是比较基础的概念,虽然平常几乎用不到,但C++11之后变得十分重要,它是理解 move/forward 等新语义的基础. 左值与 ...

  6. C笔记-左值与右值

    目录 前言:工欲善其事,必先利其器 两种资料 参考资料及其使用说明 官方对于左值和右值的定义 实际使用时的疑问 左值的涵盖范围 重要概念: 左值转化(lvalue conversion) 左值与指针 ...

  7. c++左值和右值

    c++编程中如果出现把一个函数的返回值.强行转化后的对象 作为函数的参数传进去时,编译器会报错的情况.这时候就该注意了,你需要把该函数的参数类型前加上const修饰. 原因在于c++的左值和右值有所区 ...

  8. c++ 左值 和 右值

    什么是lvalue, 什么是rvalue? lvalue: 具有存储性质的对象,即lvalue对象,是指要实际占用内存空间.有内存地址的那些实体对象,例如:变量(variables).函数.函数指针等 ...

  9. c++ 11 移动语义、std::move 左值、右值、将亡值、纯右值、右值引用

    为什么要用移动语义 先看看下面的代码 // rvalue_reference.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #includ ...

随机推荐

  1. Python数据基础类型-新建列表

    1,遍历列表 遍历列表的所有元素,对每个元素执行相同的操作.可使用for循环 magicians = ['alice','david','carolina'] for magician in magi ...

  2. Python 数据分析:Pandas 缺省值的判断

    Python 数据分析:Pandas 缺省值的判断 背景 我们从数据库中取出数据存入 Pandas None 转换成 NaN 或 NaT.但是,我们将 Pandas 数据写入数据库时又需要转换成 No ...

  3. Mysql数据库在建表时指定engine等于InnoDB 或MyISAM的意义

    一.ISAM和InnoDB的定义 1. ISAM ISAM是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数.因此,ISAM执行读取操作的速度很快 ...

  4. Qt项目中main主函数及其作用

    http://c.biancheng.net/view/1821.html main.cpp 是实现 main() 函数的文件,下面是 main.cpp 文件的内容. #include "w ...

  5. PAT Advanced 1006 Sign In and Sign Out (25 分)

    At the beginning of every day, the first person who signs in the computer room will unlock the door, ...

  6. ubuntu不能登陆

    开机按shift,找到之前的内核版本或者recovery 安装vmtools 报错Not enough free space to extract VMwareTools 解决办法:将此文件夹复制到另 ...

  7. Python中numpy的应用

    #创建ndarray import numpy as np nd = np.array([2,4,6,'])#numpy中默认ndarray的所有元素的数据类型是相同,如果数据的类型不同,会统一为统一 ...

  8. springboot+HttpInvoke 实现RPC调用

    开始用springboot2+hession4实现RPC服务时,发现第一个服务可以调用成功,但第二个就一直报 '<' is an unknown code.第一个服务还是可以调用的.参考网上的方 ...

  9. DDD领域驱动设计初探(四):WCF搭建

    前言:前面三篇分享了下DDD里面的两个主要特性:聚合和仓储.领域层的搭建基本完成,当然还涉及到领域事件和领域服务的部分,后面再项目搭建的过程中慢慢引入,博主的思路是先将整个架构走通,然后一步一步来添加 ...

  10. 做股票软件用的各种k线图

    这是各种k线图地址: http://echarts.baidu.com/echarts2/doc/example.html 个人公众号谢谢各位老铁支持 本人qq群也有许多的技术文档,希望可以为你提供一 ...