第十七章--不常见的控制结构
17.1--子程序中的多处返回
程序可以通过return和exit这类控制结构,在任何需要的时候退出子程序。下面给出一些使用return语句的指导原则。
(1)如果能增强可读性,那么就使用return。在某些子程序里,一旦知道了答案,就希望马上返回到调用方子程序。
(2)用防卫子句(早返回或早退出)来简化复杂的错误处理。可避免代码缩进层次过深,并且遮蔽正常情况的执行路径。
(3)减少每个子程序中return的数量。
17.2--递归
对于某些问题,使用递归会带来简单、优雅的解。但对于大多数问题来说,递归会带来简单但难懂的解。因此如果能用简单的迭代来代替递归,那就用容易理解的迭代。
1.递归的例子:如走迷宫,骑士巡游等。
2.使用递归的技巧
(1)确认递归能够停止。检查子程序,确保其中包含一条非递归路径。
(2)使用安全计数器防止出现无穷递归。如可以用类成员变量、或者把该安全技术作为参赛加以传递。
(3)把递归限制在一个子程序内。
(4)留心栈空间。要用new在堆上创建对象,而不要让编译器在栈上自动创建对象。
(5)不要用递归去计算阶乘或者斐波纳契数列。
17.3--goto
1.反对goto的论点
(1)含有goto的代码很难安排好格式。
(2)使用goto也会破坏编译器的优化特性。
(3)在实践中,goto会违背代码应该严格自上而下运行的原则。
2.支持goto的观点
(1)如果使用位置恰当,goto可以减少重复的代码。
(2)goto在分配资源、使用资源后再释放资源的子程序里非常有用。
(3)在某些情况下,goto会使代码运行速度更快、体积更小。
3.错误处理和goto
当子程序需要为数据库链接、内存或者临时文件等资源执行分配和清理操作的时候,可能会想用goto。
为了避免使用goto,你可以用下面几种方法重写代码:
(1)用嵌套的if语句重写。这种方法的最大缺点是嵌套层次太深。
(2)用一个状态变量重写代码。此时你需要创建一个表明该子程序是否处于出错状态的变量。这种方法的缺点在于使用状态变量的方法应用还不够普遍,你需要用注释解释你的意图。
(3)用try-finally重写。把最后清理代码放在finally中。
4.goto使用原则总结
(1)在那些不直接支持结构化控制语句的语言里,用goto语句去模拟那些控制结构。
(2)如果语言内置了等价的控制结构,那就不要用goto。
(3)如果是为了提高代码效率而使用goto,那么请衡量此举实际带来的性能提升。
(4)除非你要模拟结构化语句,否则尽量在每个子程序中只是用一个goto标号。
(5)除非你要模拟结构化语句,否则尽量让goto向前跳转而不要向后跳转。
(6)确认所有的goto标号都被用到了。
(7)确认goto不会产生某些执行不到的代码。