《C++primer》读书笔记----第四章:表达式

4.1基础

预算符

  C++定义了一元运算符和二元运算符,作用于一个对象的是一元运算符,作用于两个对象的被称为二元运算符。例如:解引用&是一元运算符,加号+为二元运算符。

左值和右值

  c语言中的左值是可以位于赋值语句左侧的值,右值则不能。在C++中,两者的区别则更加复杂。当一个对象被用做右值时,用的是对象的值(内容),当被用作为左值时,用的是对象的身份(在内存中的位置)

优先级与结合律

  复合表达式是指有两个或多个运算符的表达式,当存在复合表达式时,我们不得不考虑运算的优先级,例如:乘法和除法的优先级大于加法和减法,并且算术运算符满足左结合律,即当两个算术运算符优先级相同时,将按照从左向右的顺序组合运算对象。在表达式中,也可以使用括号()来优先求值

求值顺序

在C++中虽然规定了运算对象的结合方式,但没有规定运算对象按什么顺序求值,在大多数情况下不会明确指定求值的顺序,例:

int i = f1() * f2();//f1、f2是两个函数

  我们知道,这两个函数在执行乘法操作时一定会被调用,但我们无法知道f1和f2哪一个会被先调用。
  对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生为定义行为,例:

int i = 0;
cout << i << " " << ++i << endl;

该程序是未定义的,编译器可能先对++i求值,再对i求值,则输出的结果是1 1,也可能先对i求值,再对++i求值,则输出结果为0 1,甚至编译器还可能做出完全不同的操作。

4.2算术运算符

在这里插入图片描述
  上表列出了算术运算符,按照运算符的优先级分组,一元运算符的优先级最高,±的优先级最低,并且都满足左结合律,即优先级相同时,按照从左向右的顺序结合。

逻辑和关系运算符

在这里插入图片描述

逻辑运算符

  对于逻辑与运算符(&&)来说,当且仅当两个运算对象都为真时结果为真;对于逻辑或运算符(I)来说,只要两个运算对象中的一个为真结果就为真。
  逻辑与运算符和逻辑或运算符都是先求左侧运算对象的值再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时才会计算右侧运算对象的值。这种策略称为短路求值:

  • 对于逻辑与运算符来说,当且仅当左侧运算对象为真时才对右侧运算对象求值。

  • 对于逻辑或运算符来说,当且仅当左侧运算对象为假时才对右侧运算对象求值。

逻辑非运算符!,将运算对象的值取反后返回

关系运算符

  关系运算符比较运算对象的大小,并且返回布尔值,关系运算符满足左结合律,因为关系运算符返回布尔值所以将几个关系预算符写在一起通常不会得到一个正确答案,例如:

int i = 10 , j = 20 , k = 30 ;
if(k > j > i)
;//空语句

上述程序,依据经验来看,if中的表达式应该为真,但由于关系运算符返回布尔值,所以上述程序为,先判断k>j是否正确,正确则返回1,再比较1和i的大小,很明显1<i,所以if里的条件为假,想要正确表达该式,应该使用逻辑运算符:

if(j>i&&j<k)

4.4赋值运算符

赋值运算符左侧必须为一个可修改的左值

int i ;
const int j = 1;
i = 1 ;//正确
1034 = 1 ;//错误
j = 2 ;//错误,j不是一个可修改的左值

赋值运算符与其他运算符不太一样,赋值运算符满足右结合律:

int i,j;
i = j = 0 ;//两个变量都被赋值为0

赋值运算符通常会出现在条件语句中,但是由于赋值运算符优先级较低,所以需要加上括号才能满足我们的需求:

int i = 0;
while((i = get_value())!=42)
{
	//其他处理
}

注意区分赋值运算符与相等运算符:

if(j = k)
if(j == k)

两句话表达的意思完全不同,第一个=条通常情况下,条件永远为真,第二条则会判断jk是否相等,再返回相应的布尔值

4.5递增和递减运算符

  递增(++)和递减(–)运算符分为前置和后置两种用法,其中,前置是先先加一后赋值,后置是先赋值后加一,下面用具体的代码来说明:

int i = 0 , j ;
j = ++i;//j = 1,i = 1,得到递增后的结果
j = i++;//j = 1,i = 2,得到递增前的结果

建议:除非必须,否则不使用后置版本
在这里插入图片描述

4.6成员访问运算符

点运算符和箭头运算符都可以用来访问成员

string s1 = "a string",*p = &s1;
auto n = s1.size();
n = (*p).size();
n = p->size();

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

4.7条件运算符

条件运算符(?:)使用方法如下:
cond ? exprl : expr2;
  其中cond是判断条件的表达式,而expr1和expr2是两个类型相同或可能转换为某个公共类型的表达式。条件运算符的执行过程是:首先求cond的值,如果条件为真对exprl求值并返回该值,否则对expr2求值并返回该值。举个例子,我们可以使用条件运算符判断成绩是否合格:
string finalgrade = (grade < 60) ? “fail” : “pass”;
条件部分判断成绩是否小于60。如果小于,表达式的结果是"fail",否则结果是"pass"。有点类似于逻辑与运算符和逻辑或运算符(&&和I1),条件运算符只对expr1和expr2中的一个求值。

4.8位运算符

位运算符作用于整数类型的运算对象,并把运算对象看作是二进制位的集合
在这里插入图片描述
注意:对于符号位如何处理没有明确的规定,所以强烈建议仅将位运算符用于处理无符号类型

移位运算符

  首先令左侧运算对象的内容按照右侧运算对象的要求移动指定位数,然后将经过移动的左侧运算对象的拷贝作为求值结果
在这里插入图片描述

位求反运算符

  位求反运算符(~)将运算对象逐位求反后生成一个新值,将1置为0,将0置为1
在这里插入图片描述

位与、位或、位异或运算符

  对于位与运算符(&)来说,只有二者对应位上都为1,则运算结果中,该位为1,否则为0;对于位或运算符(|)来说,只要二者对应上有一个是1,则运算结果中,该位为1,否则为0;对于位异或运算符来说(^),如果两个运算对象的对应位置有且只有一个为1,则运算结果中该位为1,否则为0。
在这里插入图片描述
注意:要区分逻辑运算符与位运算符的写法

4.9sizeof运算符

  sizeof运算符返回一条表达式或一个类型名字所占的字节数,sizeof运算符满足右结合律。sizeof有两种使用方法:
sizeof(type)或者sizeof expr,在第二种类型中,sizeof返回表达式结果类型的大小,与众不同的是,sizeof运算符并不实际计算其运算对象的值,例如:

int *p;//指针不初始化
sizeof *p;//正确,sizeof不计算值,所以即使p是一个无效指针也无所谓。

4.10逗号运算符

  逗号运算符含有两个运算对象,按照从左到右的顺序求值。对于逗号运算符来说,首先对左侧表达式求值,然后将求值结果丢掉,逗号运算符真正的结果是右侧表达式的值。如果右侧运算对象是左值,那么最终的求值结果也是左值

4.11类型转换

如果两种类型可以相互转换,则称两种类型是关联的

int i = 3.14 + 1 ;

上面代码中,左侧为int类型,3.14为double类型,1为int类型,编译器不会直接将两个数相加,而是转换为同一种类型再进行运算,编译器会先将1转换为double类,再相加,最后将结果转换为int类,结果为4.

4.12运算符优先级表

在这里插入图片描述
在这里插入图片描述

小结

C++提供了许多运算符供程序员使用,本文介绍的内容与原文还是相差甚远,读者还需阅读原文才能更好的掌握。(由于篇幅过长,本章随堂练习将在下一篇博客书写)。

  • 21
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值