C++学习笔记:表达式

表达式由一个或多个运算对象组成,对表达式求值将得到一个结果。字面值和变量是最简单的表达式,其结果就是字面值和变量的值。把一个运算符和一个或多个运算对象组合起来可以生成较复杂的表达式。

基础

1、基本概念

一元运算符

二元运算符

三元运算符

左值和右值

  C++的表达式要么是左值,要么就是右值。

  当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。

  在需要右值的地方可以用左值来代替,但是不能把右值当成左值使用。

2、优先级与结合律

  复合表达式是指含有两个或多个运算符的表达式。求复合表达式的值需要首先将运算符和运算对象合理地组合在一起,优先级与结合律决定了运算对象组合的方式。

括号无视优先级与结合律

3、求值顺序

优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么顺序求值。在大多数情况下,不会明确指定求值的顺序。

int i=f1()*f2();

上述就无法知道到底f1在f2之前调用,还是f2在f1之前调用。

NOTE:对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为。

int i=0;

cout<

图1

算术运算符的运算对象和求值结果都是右值。在表达式求值之前,小整数类型的运算对象被提升成较大的整数类型(int),所有运算对象最终会转换成同一类型。

对大多数运算符来说,布尔类型的运算对象将被提升为int,对于一元运算符+或-,布尔值不应该参与运算。

整数相除的结果还是整数,小数部分直接弃掉。

%取余:计算两个整数相除所得的余数,运算对象必须都是整数。

逻辑和关系运算符

关系运算符作用域算术类型或指针类型,逻辑运算符作用于任意能转换成布尔值的类型。逻辑运算符和关系运算符的返回值都是布尔类型。二者的运算对象和求值结果都是右值。

图2

逻辑与和逻辑或运算符

二者都是先求左侧运算对象的值再求右侧运算对象的值。

短路求值:当左侧运算对象的值无法确定表达式的结果时才会计算右侧运算对象的值。

赋值运算符

赋值运算符的左侧运算对象必须是一个可修改的左值。

赋值运算的结果是它的左侧运算对象,并且是一个左值。相应的,结果的类型就是左侧运算对象的类型。如果赋值运算符的左右两个运算对象类型不同,则右侧运算对象转换成左侧运算对象的类型。

赋值运算满足右结合律

其他二元运算符满足左结合律,赋值运算返回的是其左侧运算对象。

赋值运算优先级较低

通常需要给赋值部分加上括号使其符合我们的原意。

不要混用赋值运算符和相等运算符

复合赋值运算符

任意一种复合运算符都完全等价于:

a=a op b;

区别在于左侧运算对象的求值次数:使用复合运算符只求值一次,使用普通运算符则求值两次。

递增和递减运算符

递增和递减运算符有两种形式:前置版本和后置版本。

前置版本是先对对象进行递增或递减运算并返回运算之后的对象值,对象本身已经发生改变。

后置版本是先返回未改变之前的对象的值,然后再对对象进行递增或递减操作。

NOTE:除非必须,否则不用递增或递减运算符的后置版本。

在一条语句中混用解引用和递增运算符

如果想在一条复合表达式中既将变量加1或减1又能使用它原来的值,这时就可以使用递增或递减的后置版本。

NOTE:后置运算符的优先级高于解引用运算符,因此*p++等价于*(p++)

成员访问运算符

点运算符和箭头运算符

NOTE:解引用运算符的优先级低于点运算符,所以执行解引用运算的子表达式两端必须加上括号。

条件运算符

条件运算符(?:)允许把简单的if-else逻辑嵌入到单个表达式中

cond?expr1:expr2

cond是判断条件的表达式,expr1和expr2是两个类型相同或可能转换为某个公共类型的表达式。

表达式的结果是expr1或expr2的返回值。当两个表达式都是左值或能转换成同一种左值类型时,运算的结果哦是左值;否则运算的结果是右值。

嵌套条件运算符

条件运算的嵌套最好别超过两到三层。

在输出表达式中使用条件运算符

条件运算符的优先级非常低,因此当一条长表达式中嵌套了条件运算子表达式时,通常需要加上括号。

位运算符

位运算符作用于整数类型的运算对象,并把运算对象看成是二进制位的集合。位运算符提供检查和设置二进制位的功能。

图3

一般来说,如果运算复习时小整型,则会自动提升成较大的整数类型。

运算对象可以是带符号,也可以是无符号。如果运算对象是带符号的且它的值为负,那么位运算符如何处理对象的“符号位”依赖于机器,左移操作可能改变符号位的值,因此是一种未定义的行为。NOTE:强烈建议仅将位运算符用于处理无符号类型。移位运算符首先令左侧运算对象的内容按照右侧运算对象的要求移动指定位数,然后将经过移动的左侧运算对象的拷贝作为求值结果。其中,右侧的运算对象一定不能为负,而且值必须严格小于结果的位数,否则产生未定义的行为。

二进制位移出边界之外的位被舍弃掉。位求反运算符位与、位或、位异或运算符sizeof运算符sizeof运算符返回一条表达式或一个类型名字所占的字节数。其值是一个size_t类型的常量表达式。sizeof并不实际计算其运算对象的值。

对char或者类型为char的表达式执行sizeof运算,结果为1对引用和解引用指针执行sizeof,得到的是实际对象所占空间的大小对指针的运算结果是指针本身所占空间的大小对数组的运算结果是整个数组所占空间的大小,等价于对数组中所有的元素各执行一次的结果之和对string和vector的执行结果是该类型固定部分的大小,不会计算对象中的元素占用了多少空间NOTE:

sizeof的返回值是常量表达式,因此可以用来定义数组。 逗号运算符逗号运算符含有两个运算对象,安装从左向右的顺序依次求值。首先对左侧的表达式求值,然后将求值结果丢弃掉,逗号运算符真正的结果是右侧表达式的值。如果右侧对象是左值,最终结果也是左值。逗号运算符经常被用在for循环中。

类型转换算术类型之间的隐式转换被设计得尽可能避免损失精度。何时发生隐式转换大多数表达式中,比int类型小的整型值首先提升为较大的整数类型在条件中,非布尔值转换成布尔类型初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型。

函数调用时也会发生类型转换算术转换运算符的运算对象转换成最宽的类型。当表达式中既有浮点又有整型的时候,整型转换为浮点。整型提升小整数类型(bool、char、signed char、unsigned char、short和unsigned short)转换成int类型较大的char类型(wchar_t、char16_t、char32_t)提升为int、unsigned、long、unsigned long、long long和unsigned long long中能容纳其值的最小的一种无符号类型的运算对象无符号类型大于带符号类型,则带符号类型转换成无符号类型无符号类型小于带符号类型,转换结果依赖于机器。其他隐式类型转换数组转换成指针在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针;

当数组被用作decltype关键字的参数,或者作为取地址符、sizeof、typeid等运算符的运算对象时,上述转换不会发生。指针的转换转换成布尔类型如果指针或算术类型的值为0,转换结果是FALSE,否则是TRUE转换成常量允许将非常量类型的指针转换成指向相应的常量类型的指针,对于引用也是这样。

相反的转换并不存在,因为它试图删除掉底层const。类类型定义的转换显式转换也称为强制类型转换。NOTE:强制类型转换很危险命名的强制类型转换cast-name(expression);其中,type是转换的目标类型而expression是要转换的值。cast-name是static_cast、dynamic_cast、const_cast和reinterpret_cast中的一种。static_cast任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast.当需要把一个较大的算术类型赋值给较小的类型时,static_cast非常有用。

它会让编译器知道我们不在乎精度损失,而不报警。static_cast对于编译器无法自动执行的类型转换也非常有用。const_castconst_cast只能改变运算对象的底层const。

常用于有函数重载的上下文中。只有const_cast能改变表达式的常量属性,使用其他形式的命名类型转换改变表达式的常量属性都将引发编译器错误。12const char *p;char *q = const_cast(p);reinterpret_cast通常为运算对象的位模式提供较低层次上的重新解释。尽量不使用。主要是指针之间的转换12int *ip;char *q = reinterpret_cast(ip);

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容

  • 人人都在受苦,无例外
    当文艺青年不再文艺阅读 179评论 0 0
  • 夏天到了,又是一个周末去哪玩呢?趵突泉五龙潭还是植物园?你自己选吧! 趵突泉!妈妈我要带上我的水枪!...
    马牙豆阅读 1,094评论 0 1
  • 有时候 你选择与某人保持距离 不是因为不在乎 而是清楚的知道她不属于你 人生遇到的每一个人 出场顺序真的很重要 如...
    Best丶456阅读 138评论 0 0
  • ​从我出国一直到我回来, 一直都有人不停的问我, 你移民了嘛?你要移民吗?外国辣么好为什么不移民? 我也一直在问自...
    Bobo波浪阅读 249评论 0 0