大胖免责声明:
我一直在想,在其他语言中使用 goto 是否真的是个坏主意。(例如 C++。)
除了一个例外(C,下面提到),它伴随着大量的纪律,它几乎从来都不是一个好主意。它取决于语言,因此请询问您当地的专家,但是您找到一个好的用例的可能性很小。谨慎行事。很可能该语言有一种更惯用和更清晰的方式来做任何你倾向于使用goto
的事情。
这与其说是“永远不可能”或“不可能停止问题”,不如说是“不切实际”。有时,特别是如果您只是通过手动编写等效goto
的 s 来隐藏循环(这是多么愚蠢的事情!),它可能会偶然起作用。在其他时候,特别是如果控制流图类似于意大利面条或其他奇怪/不寻常的情况,编译器可能无法管理任何优化。
用于创建优化通道的时间和思想只有这么多,编译器可以花在运行优化通道上的时间也只有这么多。专注于大多数语言中内置的广泛使用、易于理解的控制流模式(while
循环、具有已知开始行程计数的循环、early return
、switch
、chain ofelse if
等)会更有价值。即使优化发生在仅支持的 IR 上goto
-esque 控制流,这些模式导致可预测的、易于识别的伪装,并且优化被调整以寻找那些。这就是你引用的第二句话所说的。如果代码以与循环完全不同的方式来回跳转,则循环展开传递不会给它一天中的时间,即使它实际上是一种聪明(糟糕的聪明)编写方式“做四次”。
到目前为止,我一直假设goto
与标准 C 中的标签类似——也就是说,目标标签是静态已知的,并且仅限于尊重其他语言结构(例如,仅在一个函数内跳转)。有一些扩展允许跳转到任意的、动态选择的目标(例如“计算的 goto”)。这些更难分析(并因此优化),可能与函数指针在同一个球场。
有人告诉我这是 goto evil,但没有人告诉我为什么,除了带有 goto 的代码很难阅读。好吧,如果没有人学习,了解如何使用它们,因为它们是“邪恶的”,那么没有人可以阅读它们。
那么那些告诉你的人做得不好。这不是它的问题,所以我会保持简短:99% 的控制流适合极少数需要专门控制流构造的类别。对于所有这些情况,使用单个构造 GOTO 会掩盖意图,它需要更多代码,并且需要更长的时间才能大致了解代码在做什么。您可以亲身体验:编写一些相当复杂的 > 100 行批处理文件(那种可怕的古老的 Windows 脚本语言)。
啊,还有一件事:
我发现 GOTO 很有帮助,比如跳出嵌套循环
这可能是一个很好的用途,但大多数语言都提供了更清晰的方法。或者,将循环展平(例如使用 Python 的itertools.combinations
)和break
,或将嵌套循环放入单独的函数中(在许多情况下无论如何都是好主意)和return
.
此外,这些都是. goto
例如,C 语言中的错误处理。这些用例通常也符合一种简单的模式,但这种模式并未内置于语言中,因此只能勉强使用。