我已经编写了一些PL / SQL程序,我发现GOTO很有帮助,比如跳出嵌套循环等等。
我一直在想,如果在其他语言中使用gotos真是个坏主意。 (例如C ++。)
我发现了这些问题:
GOTO still considered harmful?
effect of goto on C++ compiler optimization
答案是:"编译器通常无法优化包含gotos的代码。"
而在另一个中:"然而,有可能生成一个带有gotos的流程图,这些流图不能由任何正常的流控制语句(循环,开关等)产生&# 34;
我已经被告知过了邪恶,但是没有人告诉我为什么,除了带有gotos的代码很难阅读。好吧,如果没有人学习,了解如何使用它们,因为它们是“邪恶的”,没有人可以阅读它们。
当编译器CAN和CAN不优化包含GOTO的代码时会出现什么情况?为什么?
答案 0 :(得分:2)
大胖子免责声明:
我一直在想,如果在其他语言中使用gotos真是个坏主意。 (例如C ++。)
除了一个与大量纪律相结合的例外(C,如下所述),它几乎从来都不是一个好主意。这是依赖于语言的,所以请问你当地的大师,但是你找到一个好的用例的可能性相当小。呃谨慎一点。机会有一种更惯用和更清晰的方式来做任何你倾向于使用goto
的事情。
这不是一个“不能永远”或停止 - 问题 - 不可能的情况,因为“只是不切实际”。有时,特别是如果你只是通过手动编写等效的goto
来隐藏你的循环(这是一个愚蠢的事情!),它可能是偶然的。在其他时候,特别是如果控制流图类似于意大利面条或者奇怪/异常,编译器可能无法管理优化任何内容。
只有这么多时间和思考才能创建优化传递,并且编译器只需花费很多时间来运行优化传递。专注于大多数语言(while
循环,具有已知起始行程计数,早期return
,{{1}的循环,广泛使用,易于理解的控制流模式更有意义。 },switch
的链等。即使优化发生在仅 支持else if
- esque控制流的IR上,这些模式也会导致可预测的,容易识别的伪装,并且优化被调整为寻找那些。这就是你引用的第二句话。如果代码以一种完全不同于循环的方式来回跳转,那么循环展开将不会给它一天中的时间,即使它实际上是一种聪明的(不好的聪明)写作方式“这样做四次”
到目前为止,我假设goto
类似于标准C中的那个 - 也就是说,目标标签是静态已知的并且仅限于遵守其他语言结构(例如,仅在一个函数内跳转)。存在允许跳转到任意动态选择的目标(例如“计算的转到”)的扩展。这些很难分析(并因此优化),可能与函数指针在同一个球场中。
我被告知这是邪恶的,但没有人告诉我为什么,除了带有gotos的代码是可怕的阅读。好吧,如果没有人学习,了解如何使用它们,因为它们是“邪恶的”,没有人可以阅读它们。
那些告诉你的人做得不好。这不是问题所在,所以我会保持简短:99%的控制流程适合很少的类别,这些类别需要专门的控制流程结构。对于所有这些情况,使用单个构造GOTO模糊了意图,代码更多,并且需要更长时间才能理解代码正在做什么。您可以亲身体验一下:编写一些相当复杂的> 100行批处理文件(那种可怕的古老Windows脚本语言)。
啊,还有一件事:
我发现GOTO很有帮助,比如跳出嵌套循环
这可能是一种很好的用途,但大多数语言提供了更清晰的方法。或者,将循环展平(例如使用Python的goto
)和itertools.combinations
,或者将嵌套循环放入单独的函数(在许多情况下无论如何都是好主意)和break
。
此外,这些 是return
的良好用途。例如,C语言中的错误处理。这些用例通常也符合一个简单的模式,但是没有内置到语言中的模式,所以必须要做到这一点。