左值&右值
一、引子
我们所谓的左值、右值,正确的说法应该是左值表达式、右值表达式。
因为C++的表达式不是左值就是右值。
在C中,左值指的是既能够出现在等号左边也能出现在等号右边的表达式,右值指的则是只能出现在等号右边的表达式。
而在C++中,二者的区别就不是这么简单了。
二、关键点
【官方定义】
- 一个左值表达式的求值结果是一个对象或者一个函数,而某些右值表达式的求值结果也是对象;
- 以常量对象为代表的某些左值并不能作为赋值语句的左侧运算对象。
- 归纳:当一个对象被用作右值的时候,用的是对象的值(内容);而被用作左值的时候,用的是对象的身份(在内存中的位置)。
【解读定义】
解读第一句:既然左值和右值都可以是对象,那怎么区分一个对象是左值还是右值呢?
- 左值:能用“取地址&”运算符获得对象的内存地址
- 右值:不能用“取地址&”运算符获得对象的内存地址
- 特例:因为可以用&取得字符串字面值常量的地址,所以它是一个左值;而其他的字面值常量则不可用&取地址,所以它们是右值
我们知道对象是一块空间,那么有哪些对象以及为什么不能用&取地址呢?
- 对于临时对象,它可以存储于寄存器中,所以没办法用“取地址&”运算符;
- 对于(非字符串)常量,它可能被编码到机器指令的“立即数”中,所以没办法用“取地址&”运算符。
解读第二句:字符串字面值常量确实不能放在等号左边啊,没错啊!
解读归纳:所以啊,左值看地址,右值看内容。
【补充】
#include <iostream> using namespace std; int& func(int &a)
{
return a; // 不能返回局部对象的引用
} int main()
{
int a = 10;
func(a) = 100; // 返回非常量引用的函数可以当作左值使用
cout << a << endl; // 输出100
return 0;
}
三、为什么要区分左值右值
- 不同的运算符对运算对象的要求各不相同,有的需要左值运算对象、有的需要右值运算对象;返回值也有差异,有的得到左值结果、有的得到右值结果。
举例:使用关键字decltype的时候,其表达式的求值结果若是左值,decltype作用于该表达式(不能是变量)得到一个引用类型。例如,p的类型是int *,因为解引用运算符生成左值,所以decltype(*p)的结果是int &。而另一方面,因为取地址运算符生成右值,所以decltype(&p)的结果是int **,即结果是一个指向整型指针的指针。
左值&右值的更多相关文章
- c++ 左值右值 函数模板
1.先看一段代码,这就是一种函数模板的用法,但是红色的部分如果把a写成a++或者写成一个常量比如1,都是编译不过的,因为如果是a++的话,实际上首先是取得a的 值0,而0作为一个常量没有地址.写成1也 ...
- C++ 左值 右值
最近在研究C++ 左值 右值,搬运.收集了一些别人的资料,供自己记录和学习,若以后看到了更好的解释,会继续补充.(打“?”是我自己不明白的地方 ) 参考:<Boost程序库探秘——深度解析C ...
- C++ 左值与右值 右值引用 引用折叠 => 完美转发
左值与右值 什么是左值?什么是右值? 在C++里没有明确定义.看了几个版本,有名字的是左值,没名字的是右值.能被&取地址的是左值,不能被&取地址的是右值.而且左值与右值可以发生转换. ...
- C++11之右值引用(一):从左值右值到右值引用
C++98中规定了左值和右值的概念,但是一般程序员不需要理解的过于深入,因为对于C++98,左值和右值的划分一般用处不大,但是到了C++11,它的重要性开始显现出来. C++98标准明确规定: 左值是 ...
- C语言几个术语: 数据对象,左值,右值
1. 数据对象 赋值表达式语句的目的是把值存储到内存位置上. 用于存储值的数据存储区域统称为数据对象. 2. 左值 左值是C语言的术语, 用于标识特定数据对象的名称或表达式. 对象指的是实际的数据存储 ...
- i++和++i以及左值,右值
左值(LValue)和右值(RValue)的一个快捷记法是赋值运算,左值是赋值运算左边的值,右值就是右边(=,=废话).例如: int a = 5; a就是左值,5就是右值. 当然,如果真是这么个含义 ...
- C和C指针小记(八)-操作符、左值右值
1.移位操作符 移位操作符分为左移操作符(<<)和右移操纵符(>>) 对于无符号数:左右位移操作都是逻辑位移 对于有符号数:到底是采用逻辑位移还是算术位移取决于编译器.如果一个 ...
- C++中的左值与右值(二)
以前以为自己把左值和右值已经弄清楚了,果然发现自己还是太年轻了,下面的这些东西是自己通过在网上拾人牙慧,加上自己的理解写的. 1. 2. 怎么区分左值和右值:知乎大神@顾露的回答. 3. 我们不能直接 ...
- C语言 左值、右值
左值就是在赋值中可以放在赋值操作符两边的值 右值则是只可以放在赋值操作符右边的值 ++i是直接给i变量加1,然后返回i本身,因为i是变量,所以可以被赋值,因此是左值表达式i++现产生一个临时变量,记录 ...
随机推荐
- HDU1398 Square Coins(生成函数)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- 解决MacOS升级后出现xcrun: error: invalid active developer path, missing xcrun的问题
升级了系统 命令行不能用了 xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), mis ...
- idea 聚合项目里如果子项目引用不到父类的maven应用
idea 聚合项目里如果子项目引用不到父类的maven应用,可以点看子类pom.xml文件,然后右键---->maven----->Reimport即可 点击右边子项目的maven---& ...
- pt-online-schema-change在线修改表结构
工具简介 pt-osc模仿MySQL内部的改表方式进行改表,但整个改表过程是通过对原始表的拷贝来完成的,即在改表过程中原始表不会被锁定,并不影响对该表的读写操作.首先,osc创建与原始表相同的不包含数 ...
- 前端模块化小总结—commonJs,AMD,CMD, ES6 的Module
随着前端快速发展,需要使用javascript处理越来越多的事情,不在局限页面的交互,项目的需求越来越多,更多的逻辑需要在前端完成,这时需要一种新的模式 --模块化编程 模块化的理解:模块化是一种处理 ...
- python函数基本介绍
函数 1.函数结构 def 是函数的定义关键字,my_len是函数名.()传参用,冒号下面都是函数体. 执行函数方法:函数名加括号来执行函数.My_len() 举例: # s = 'lkfjsjulk ...
- Filter(过滤器)与Interceptor(拦截器)的区别
Filter能够对请求和响应资源进行拦截: Interceptor只针对请求进行拦截 在 Struts2中: (1)拦截器是基于java反射机制的,而过滤器是基于函数回调的. (2)过滤器依赖与ser ...
- thinkphp5 部署到iis服务器url重写
thinkphp部署到iis服务器配置url重写的解决方法: 1.下载 url rewrite.下载地址:https://www.iis.net/downloads/microsoft/url-rew ...
- MySQL高级-性能分析Explain
1.使用Explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的.分析你的查询语句或是表结构的性能瓶颈 . 2.执行方法:Explain + SQL语句 解释 ...
- 金山WPS面试题
1.windows的handle 1)是一个宏定义#define void* HANDLE 2) HANDLE提供了一种统一的方式去获得系统资源,并对其进行操作. 3) HANDLE使得程序设计的细节 ...