子程序中的多处返回
程序可以通过return
和exit
这类控制结构,在任何需要的时候退出子程序。
- 如果能增强可读性,那么就使用
return
; - 用防卫子句(早返回或早退出)来简化复杂的错误处理;
- 减少每个子程序中
return
的数量。
递归
在递归里面,一个子程序自己负责解决某个问题的一小部分,它还把问题分解成许多的小块,然后调用自己来分别解决每一小块。
使用递归的技巧
- 确认递归能够停止;
- 使用安全计数器防止出现无穷递归;
- 把递归限制在一个子程序内;
- 留心栈空间;
- 不要用递归去计算阶乘或者斐波那契数列;
go to
反对go to的论点
人们反对使用goto
的普遍理由是:没有使用goto
的代码就是高质量的代码。
- 含有
goto
的代码很难安排好格式; - 使用
goto
也会破坏编译器的优化特性; - 使用
goto
会使代码更小,运行更快; - 使用
goto
会违背代码应该严格自上而下运行的原则。
支持go to的观点
goto
的支持者们通常都会强调要在特定的场合下谨慎地使用goto
,而不要不分青红皂白地用。
- 如果使用位置恰当,
goto
可以减少重复的代码; goto
在分配资源、使用资源后再释放资源的子程序里非常有用;- 在某些情况下,使用
goto
会让代码的运行速度更快,体积更小; - 编程水平高不等于不使用
goto
; - 很多现代语言已经包含了
goto
。
goto使用原则总结
- 在那些不直接支持结构化控制语句的语言里,用
goto
去模拟那些控制结构; - 如果语言内置了等价的控制结构,那么就不要用
goto
; - 如果是为了提高代码效率而使用
goto
,请衡量此举实际带来的性能提升; - 除非你要模拟结构化语句,否则尽量在每个子程序内只是用一个
goto
标号; - 除非你要模拟结构化语句,否则尽量让
goto
向前跳转而不要向后跳转; - 确认所有的
goto
标号都被用到了; - 确认
goto
不会产生某些执行不到的代码; - 对某一个
goto
用法所展开的争论并不是事关全局的;
核对表:不常见的控制结构
return
- [ ] 每一个子程序都仅在有必要的时候才使用
return
吗? - [ ] 使用
return
有助于增强可读性吗?
递归
- [ ] 递归子程序包含了停止递归的代码吗?
- [ ] 子程序用安全计数器来确保该子程序能停下来吗?
- [ ] 递归只位于一个子程序里面吗?
- [ ] 子程序的递归深度处于程序栈容量可以满足的限度内吗?
- [ ] 递归是实现子程序的最佳方法吗?它要好于简单的迭代吗?
goto
- [ ] 是否只有在万不得已的时候才使用
goto
?如果使用了goto
,是否仅仅是出于增强可读性和可维护性呢? - [ ] 如果是出于效率因素而使用的
goto
,那么对这种效率上的提升做出衡量并且加以说明了吗? - [ ] 一个子程序里最多只用了一个
goto
标号吗? - [ ] 所有的
goto
都向前跳转,而不是向后跳转吗? - [ ] 所有的
goto
标号都用到了吗?
要点
- 多个
return
可以增强子程序的可读性和可维护性,同时可以避免产生很深的嵌套逻辑; - 递归能够很优雅地解决一小部分问题。对它的使用也要加倍小心;
- 在少数情况下,
goto
是编写可读性和可维护代码的最佳方法。但这种情况非常罕见。除非万不得已,不要使用goto
。