稍有点晚的周更
第五章的标题是语句,主要讲的是我们平时写语句的一些基本要求和例如迭代语句控制语句等概念。这篇内容比较少而且因为平时用得很多所以写的自然也会少些。
5.1-5.2 语句基础
- 最简单的语句是空语句,也就是只有分号的语句。其可以放在语法需要语句但是逻辑不需要的地方。
- 在使用空语句时最好有注释,因为很容易打乱迭代或控制语句的安排。
- 相对应的,用花括号括起来的多条语句称为复合语句或语句块,在花括号中的变量有同个作用域,空块相当于空语句。
- 除了在for和while的控制结构(小括号内)可以定义变量,我们同样也可以在if和switch中定义,不过没什么很大需要。
- 定义在控制结构中的变量只能在那个控制语句中有效。
5.3 条件语句
- if语句要求控制结构中表达式的类型必须可以转为bool
- if语句可以层层嵌套,else if其实是嵌套if的一种不同的缩进而已,并不是特别的写法。
- 有的编码风格建议在if和else后面都使用花括号使得代码清晰
- 在C++来说,else语句默认是与当前仍未匹配的最接近的if进行匹配,称为悬垂else问题
- switch语句要求控制结构中表达式类型必须可转为整形
- switch的每个case都需要是常量整形且不能重复
- case不一定要break,可以故意省略break来达成多个case一口气执行,不过当使用这种写法时建议一边加上注释,一边将多个case写到同一行以强调其统一性。
- default标签会在没有任何case匹配时触发,即使不需要这种情况也建议写上一个空的default并加上注释。
- switch语句由于会进行语句跳转,要求不能跳过变量的初始化而使用变量,且每个case都有内部的一个作用域。
5.4 迭代语句- 只要控制结构中为真while便会不断执行循环体,如果在while的控制结构或循环体中定义变量的话,这个变量将会在每次迭代中创建又销毁
- 一般来说while用在不能确定迭代的次数或者希望在循环结束时访问循环的控制变量的情况
- 传统的for结构的语句头中:初始化部分用于初始化控制变量,控制部分用于判断是否为真,只有真的时候才会执行循环体,然后修改部分用于改变控制变量,修改发生在每一轮迭代之后。
- for的语句头中任何部分都可以被省略,但是要注意会不会一不小心无限循环
- C11引入了新的for语句也就是目前很多其他语言都很流行的range-for语句,即范围for语句,之前我们也有提到。结构是for (declaration: expression) statement
- 范围for语句最重要的要求就是expression部分必须是序列,也就是可以得到begin-end成员的序列,且序列中每个元素都要和declaration符合,为保证符合最好的方法是使用auto
- 范围for语句会在每次迭代中将声明转为序列的下一个值,然后在执行循环体。由于范围for语句其实是传统for的变体,在开始循环时就储存了序列的begin和end,所以不要在循环中修改序列的长度导致begin-end改变
- do-while语句使得无论条件部分如何都会至少执行一次do中的代码,但是要注意的就是由于这个特点我们不能在do的控制体中定义变量,控制变量需要提前在外部定义
5.5 跳转语句
- C有4种跳转语句break,continue,goto,return。return下篇再写。
- break语句只能终止最接近的一层循环或者switch,也只能出现在这些语句之中,终止这一层后在外层接下来的第一句语句继续执行。
- continue语句则是终止最接近的一层循环然后立即开始下一次循环(包括条件判断),除非switch嵌套在循环中否则不能在swicth中用。
- goto语句是十分不推荐使用的语句,它太底层太暴力了,很容易让程序变得很乱,所有的goto都能转为循环
- goto语句与swicth类似,不能将程序的运行凌驾在变量的作用域上,也就是不能跳转到变量的定义之后来使用它,而如果跳转回变量的定义之前则相当于将变量销毁并重新创建。
5.6 异常语句
- C++的异常编写其实和我们更加熟悉的Java很像,同样的写法,同样需要在try中throw出异常对象然后用catch捕获并处理,所以要写的东西反而没那么多。
- C++的异常类在标准库中有定义,分别在stdexcept,exception,new,type_inifo四个头文件中,每个异常我们使用它们都有的what函数来得到异常的信息。
- stdexcept是平时最常用的头文件,文末有这个头文件中的异常类列表,在初始化这个异常对象时需要带入参数string,自己决定此异常抛出的信息。
- exception头文件中定义了最通用的异常类exception。这个类只抛出异常不描述信息。
- new头文件中定义了后面会说到的bad_alloc类型。
- type_info定义了更后面会说到的bad_cast类型。
- 后面的这三个头文件只能进行默认构造初始化,其what内容由编译器决定。
- 要注意抛出异常会中断当前的程序转为异常处理,这其中被中断的各种变量和状态的处理很难把控,编写异常安全的代码是很困难的。
- 当catch不到所抛出的异常时这个异常会继续往上一层抛,这个过程与函数的层层调用刚好相反,当抛到无法再抛(第一层)时,程序会转到terminate函数中,绝大多数情况下这会导致程序非正常终止。
<stdexcept>定义的异常类