3

我编写了一些 PL/SQL 程序,我发现 GOTO 很有帮助,比如跳出嵌套循环等。

我一直在想,在其他语言中使用 goto 是否真的是个坏主意。(例如 C++。)

我发现了这些问题:

GOTO 仍然被认为是有害的?

goto 对 C++ 编译器优化的影响

有一个答案说:“编译器通常无法优化包含 goto 的代码。”

而在另一个中:“但是,有可能生成一个带有 goto 的流程图,而这是任何正常的流控制语句(循环、开关等)都无法生成的。”

有人告诉我这是 goto evil,但没有人告诉我为什么,除了带有 goto 的代码很难阅读。好吧,如果没有人学习,了解如何使用它们,因为它们是“邪恶的”,那么没有人可以阅读它们。

编译器可以和不能优化包含 GOTO 的代码的情况是什么?为什么?

4

1 回答 1

2

大胖免责声明:

我一直在想,在其他语言中使用 goto 是否真的是个坏主意。(例如 C++。)

除了一个例外(C,下面提到),它伴随着大量的纪律,它几乎从来都不是一个好主意。它取决于语言,因此请询问您当地的专家,但是您找到一个好的用例的可能性很小。谨慎行事。很可能该语言有一种更惯用和更清晰的方式来做任何你倾向于使用goto的事情。


这与其说是“永远不可能”或“不可能停止问题”,不如说是“不切实际”。有时,特别是如果您只是通过手动编写等效goto的 s 来隐藏循环(这是多么愚蠢的事情!),它可能会偶然起作用。在其他时候,特别是如果控制流图类似于意大利面条或其他奇怪/不寻常的情况,编译器可能无法管理任何优化。

用于创建优化通道的时间和思想只有这么多,编译器可以花在运行优化通道上的时间也只有这么多。专注于大多数语言中内置的广泛使用、易于理解的控制流模式(while循环、具有已知开始行程计数的循环、early returnswitch、chain ofelse if等)会更有价值。即使优化发生在支持的 IR 上goto-esque 控制流,这些模式导致可预测的、易于识别的伪装,并且优化被调整以寻找那些。这就是你引用的第二句话所说的。如果代码以与循环完全不同的方式来回跳转,则循环展开传递不会给它一天中的时间,即使它实际上是一种聪明(糟糕的聪明)编写方式“做四次”。

到目前为止,我一直假设goto与标准 C 中的标签类似——也就是说,目标标签是静态已知的,并且仅限于尊重其他语言结构(例如,仅在一个函数内跳转)。有一些扩展允许跳转到任意的、动态选择的目标(例如“计算的 goto”)。这些更难分析(并因此优化),可能与函数指针在同一个球场。

有人告诉我这是 goto evil,但没有人告诉我为什么,除了带有 goto 的代码很难阅读。好吧,如果没有人学习,了解如何使用它们,因为它们是“邪恶的”,那么没有人可以阅读它们。

那么那些告诉你的人做得不好。这不是它的问题,所以我会保持简短:99% 的控制流适合极少数需要专门控制流构造的类别。对于所有这些情况,使用单个构造 GOTO 会掩盖意图,它需要更多代码,并且需要更长的时间才能大致了解代码在做什么。您可以亲身体验:编写一些相当复杂的 > 100 行批处理文件(那种可怕的古老的 Windows 脚本语言)。

啊,还有一件事:

我发现 GOTO 很有帮助,比如跳出嵌套循环

这可能是一个很好的用途,但大多数语言都提供了更清晰的方法。或者,将循环展平(例如使用 Python 的itertools.combinations)和break,或将嵌套循环放入单独的函数中(在许多情况下无论如何都是好主意)和return.

此外,这些都是. goto例如,C 语言中的错误处理。这些用例通常也符合一种简单的模式,但这种模式并未内置于语言中,因此只能勉强使用。

于 2013-07-19T20:38:48.727 回答