2022.11月代码大全阅读笔记1
第十七章阅读笔记
17.1 子程序中的多处返回
多数语言都提供了某种半途退出子程序的方法。程序可以通过 return 和 exit这类控制结构,在任何需要的时候退出子程序。它导致子程序按照正常的退出途径终止,并把控制权转交给调用方子程序。在这里,我们用 return 这一词语泛指C++和 Java 中的 return, Microsoft Visual Basic 中的 Exit Sub 和 Exit Function, 以及与之相似的其他结构。
1、如果能增强可读性,那么就使用 return。 在某些子程序里,一旦知道了答案,你会希望马上返回到调用方子程序。如果子程序被定义为检测出错误以后不再做任何更多的清理操作,那么不马上返回就意味着你还得写更多的代码。
2、用防卫子句(guard clause)(早返回或早退出)来简化复杂的错误处理。 如果代码中必须要在执行正常操作之前做大量的错误条件检测,就很可能导致代码的缩进层次过深,并且遮蔽正常情况的执行路径。从审美的角度来说,把子程序的主体缩在4条 if 语句里面很难看,尤其是当最里层 if语句的代码非常多的时候。在这种情况下,如果先检查错误情况,用这些代码来为正常的执行路径清路,那么代码的布局有时可能变得更清楚
3、减少每个子程序中 return 的数量。如果在读子程序的后部时,你没有意识到它从前面某个地方返回的可能性,想理解这个子程序就很困难。由此可见,使用return 要十分审慎——只当它们能增强可读性的时候才去使用。
17.2 递归
在递归(recursion)里面,一个子程序自己负责解决某个问题的一小部分,它还把问题分解成很多的小块,然后调用自己来分别解决每一小块。当问题的小部分很容易解决,而问题的大部分也很容易分解成众多的小部分时,常常会用到递归。
17.2.1 使用递归的技巧
确认递归能够停止 。 检查子程序以确认其中含有一条非递归的路径。通常这意味着该子程序中含有一项判断,无须进一步递归就能停下来。
使用安全计数器防止出现无穷递归。 如果你在一种不允许使用上述简单测试的环境中使用递归,那么就用安全计数器来防止产生无穷递归。该安全计数器必须是一个不随每次子程序调用而重新创建的变量。可以用一个类成员变量,或者把该安全计数器作为参数加以传递.
首先,计算机科学教程中给出的递归示例没有给这个世界带来任何的好处。
其次,也是更为重要的,递归是一种非常强大的工具,其功能之强大要远远超出使用它们来稀里糊涂地计算阶乘或者斐波纳契数列。
再次,也是最重要的,在用递归之前你应该考虑它的替换方案。你用递归能做到的,同样也可以用栈和循环来做到。有时候用这种方法好;有时用另一种方法好。在你定下来使用哪种方法之前,请把两者都考虑一下。
17.3 goto
在现代高级语言中,大部分问题不需要goto,小部分需要goto的问题中,也有一大部分可以转换为其他结构。goto太危险,因此要少用。一些原则如下:
不要用goto完成完全可以用已有的规范控制结构完成的工作。
如果语言内置了等价的控制结构,不要用goto完成。
如果试图用goto提高性能,要审慎衡量得失。
每个程序内尽量只使用一个标号
尽量让goto向前跳转而非向后跳转
确认所有goto标号都被用到了,删除无用的标号
确认goto不会产生不可达的代码。