前言

为了了解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. NOIP赛前集训备忘录(含每日总结)(日更?。。。)

    NOIP赛前集训备忘录(含每日考试总结) 标签: 有用的东西~(≧▽≦)/~啦啦啦 阅读体验:https://zybuluo.com/Junlier/note/1279194 考试每日总结(这个东西是 ...

  2. win10无法开启网络发现怎么办 如何启用网络发现

    鼠标右键点击桌面左下角的开始按钮,在弹出的菜单中选择“运行”菜单项.   在打开的Windows10运行窗口中,输入Services.msc,然后点击确定按钮.   在打开的Windows10服务窗口 ...

  3. 一:jvm的五大内存区(内存结构)

    jvm五大内存区域(即jvm运行时数据区),描述的是类被加载时,经过解析后,存储到特定的数据区.方法区和堆是所有线程共享的,而栈和计数器是线程私有的.栈处理程序运行的问题,堆处理数据的存储问题.所以才 ...

  4. Linux文档整理之【Mysql安装与配置】

    最近公司让整理一个Linux安装Mysql的文档.所以就整理了一下,这里将自己整理的详细文档做个笔记. 1.下载Mysql. https://dev.mysql.com/downloads/mysql ...

  5. 【问题解决方案】git仓库重构

    Linux mv命令 用来为文件或目录改名.或将文件或目录移入其它位置. 语法 mv [options] source dest mv [options] source... directory 注: ...

  6. (架构)React Native 导出项目全局共用组件的模块

    自定义组件全局使用(类似如下) import { ReactNavComponent, Widget, Util } from 'rn-yunxi'; const { RegexpUtil, Stor ...

  7. Mysql 服务器管理程序 mysqladmin

    mysqladmin [oprions] command 选项                                      说明 create db_name               ...

  8. STM32 GPIO相关

    1. STM32 的 IO 作为输入的时候,可以程序设置上下拉电阻(可以不用外接上下拉电阻). 2.GPIO有四种输入模式:浮空输入.上拉输入.下拉输入.模拟输入: 3.GPIO有四种输出模式:开漏输 ...

  9. 006-(成功环境记录)基于Centos7系统部署cobbler批量安装系统

    1.1 cobbler简介 Cobbler是一个Linux服务器安装的服务,可以通过网络启动(PXE)的方式来快速安装.重装物理服务器和虚拟机,同时还可以管理DHCP,DNS等. Cobbler可以使 ...

  10. ascii 八进制

    int main() 4 { 5 char buf[20] = {'\101','\102','\103',0}; 6 printf("%s",buf); 7 return 0; ...