第四章~第五章

第四章 表达式

4.1    基础

1、左值和右值:C++的表达式要么是右值,要么是左值。当一个对象被用作左值时,用的是对象的身份(在内存中的位置);用作右值时,用的是对象的值(内容)。一般情况下,在需要右值时,可以用左值替代,此时使用左值对象的内容,但是需要左值的时候不能用右值替代。另外要注意,只有可修改的左值才能放在赋值语句的左侧,常量对象虽然也是左值,但是不能放在赋值语句的左侧。

2、如果表达式的求值结果是左值,decltype作用于该表达式(不是变量)得到一个引用类型。

3、研究表达式要搞清楚各运算符的优先级,结合律和求值顺序。

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

int i = 0; 
cout << i << " " << ++i << endl; // 未定义的

5、建议:处理复合表达式(P123):1、拿不准时最好用括号;2、如果改变了某个运算对象的值,在表达式的其他地方不要再使用这个运算对象。

4.2--4.5    算术运算符,逻辑和关系运算符,赋值运算符,递增和递减运算符

1、在除法运算中,C++11新标准规定商一律向0取整(即直接切除小数部分);根据取余运算的定义,如果m和n是整数且n非0,则表达式 (m / n) * n + m % n 的求值结果与m相等。隐含的意思是,如果m % n不等于0,则它的符号与m相同。

2、短路求值:逻辑与运算符和逻辑或运算符都是先求左侧运算对象的值再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时才会计算右侧表达式的值。

3、进行比较运算时除非比较的对象是布尔类型,否则不要使用布尔字面值true和false作为运算对象(P128)

4、赋值运算优先级较低,赋值运算满足右结合律,切勿混淆相等运算符和赋值运算符。

5、复合运算符与其等价写法a = a op b的唯一区别是左侧运算对象的求值次数,前者只求值一次,后者求值两次。

6、建议:除非必须,否则不用递增递减运算符的后置版本(P132)

7、建议:简洁可以成为一种美德(P132)

4.6--4.9    成员访问运算符,条件运算符,位运算符,sizeof运算符

1、点运算符和箭头运算符都可用于访问成员。因为解引用运算符的优先级低于点运算符,所以执行解引用的子表达式两端必须加上括号。

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

3、强烈建议仅将位运算符用于处理无符号类型,因为关于符号位如何处理没有明确的规定。

4、对string和vector对象执行sizeof运算只返回该类型固定部分的大小,不会计算对象中的元素占用了多少空间。即结果与元素类型,元素个数无关。

4.10--4.12    逗号运算符,类型转换,运算符优先级表

1、算术类型之间的隐式转换被设计得尽可能避免损失精度。很多时候,如果表达式中既有整数类型的运算对象也有浮点数类型的运算对象,整型会转换成浮点型。

2、整型提升:在表达式中,小整型通常会被提升成int(如果int能容纳该小整型所有可能的值)。

3、强制类型转换: cast-name<type>(expression),type是转换的目标类型而expression是要转换的值。如果type是引用类型,则结果是左值。cast-name是static_cast、dynamic_cast、const_cast和reinterpret_cast中的一种。

4、建议:避免强制类型转换,特别的,使用reinterpret_cast是非常危险的。(P146)

5、旧式的强制类型转换,如果换成const_cast或static_cast也合法,则其行为与对应的命名转换一致,否则,其行为与reinterpret_cast类似。与命名的强制类型转换相比,旧式的强制类型转换从表现形式上来说不那么清晰明了,容易被看漏,所以一旦转换过程出现问题,追踪起来也更加困难。

6、运算符优先级表(P147-148)

第五章 语句

5.1--5.2    简单语句,语句作用域

1、表达式语句的作用是执行表达式并丢弃掉求值结果。

2、可以在if、switch、while和for语句的控制结构内定义变量。定义在控制结构当中的变量只在相应语句的内部可见,一旦语句结束,变量也就超出其作用范围了。

5.3--5.4    条件语句,迭代语句

1、悬垂else:默认else与最近的if匹配,所以在if多于else时若想要控制程序执行路径,可以使用花括号。

2、C++语言规定,不允许跨过变量的初始化语句直接跳转到该变量作用域中的另一个位置。如果需要为某个case分支定义并初始化一个变量,我们应该把变量定义在块内,从而确保后面的所有case标签都在变量的作用域之外。(P163)

3、while和do while语句中的condition部分(即括号内部分)不能为空,但for语句可以;另外,while可以在条件部分定义变量,而对于do while来说先执行语句或者块,后判断条件,所以不允许在条件部分定义变量。

4、范围for语句中expression表示的必须是一个序列,比如用花括号括起来的初始值列表、数组或者vector或string等类型的对象,这些类型的共同特点是拥有能返回迭代器的begin和end成员;而declaration确保类型相容最简单的办法是使用auto类型说明符,如果需要对序列中的元素执行写操作,循环变量必须声明成引用类型。

5.5--5.6    跳转语句,try语句块和异常处理

1、continue语句中断当前的迭代,但是仍然继续执行循环。对于while或者do while语句来说,继续判断条件的值;对于传统的for循环来说,继续执行for语句头的expression;而对于范围for语句来说,则是用序列中的下一个元素初始化循环控制变量。

2、异常处理:包括throw表达式,try语句块,一套异常类。具体写法:try中是正常程序执行代码,在可能出现异常的地方使用throw引发异常。try之后是一个或多个catch子句,用于处理异常,当选中了某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。注意:try语句块内声明的变量在块外部无法访问,特别是在catch子句内也无法访问。(P174)

3、如果最终还是没能找到任何匹配的catch子句,程序转到名为terminate的标准库函数。该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。对于那些没有任何try语句块定义的异常,也按照类似的方式处理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值