goto 几乎普遍灰心。使用此陈述是否值得?

有帮助吗?

解决方案

这已经在堆栈溢出和克里斯·吉鲁姆(Chris Gillum)上进行了多次讨论 总结了可能的用途 goto:

干净地退出功能

通常,您可以分配资源并需要在多个位置退出。程序员可以通过将资源清理代码放在功能末尾的所有“退出点”的所有“退出点”中,可以简化其代码。这样,您就不必在功能的每个“退出点”上编写清理代码。

退出嵌套环

如果您处于嵌套循环中,需要突破 全部 循环,一个goto可以使比断开语句和if-if-shecks更加干净,更简单。

低级性能改进

这仅在完美代码中有效,但是goto语句执行非常快,可以在函数中移动时为您提供增强。但是,这是一把双刃剑,因为编译器通常无法优化包含gotos的代码。

我认为,正如许多其他人会争辩的,在所有这些情况下, goto 被用作从一个拐角处编码自己的手段,通常是可以重构的代码症状。

其他提示

高级控制流构建体往往与问题域中的概念相对应。一个if/其他是基于某种条件的决定。一个循环说要反复执行一些动作。甚至休息声明也说:“我们反复这样做,但现在我们需要停止”。

另一方面,GOTO语句倾向于与运行程序中的概念相对应,而不是在问题域中。它说要继续在指定点执行 在程序中. 。有人阅读代码必须 推断 关于问题域的含义。

当然,所有高级构造都可以根据gotos和简单的条件分支来定义。这并不意味着他们只是伪装。认为他们是 受限制的 gotos-正是限制使它们有用。断路语句被实现为跳到封闭循环的末端的跳跃,但最好将其视为在整个循环中运行。

所有其他是平等的,其结构反映问题域的代码往往更易于阅读和维护。

在没有任何情况下,绝对需要goto语句(有 定理 为此),但是在某些情况下,它可能是最不好的解决方案。这些情况因语言而异,具体取决于语言支持的高级构造。

例如,在C中,我相信有三种基本场景适合goto。

  1. 从嵌套的环中脱颖而出。如果该语言具有标记为Break语句,这将是不必要的。
  2. 在发生错误或其他意外事件的情况下,请从一定代码(通常是功能主体)中释放。如果语言有例外,这将是不必要的。
  3. 实施明确的有限状态机。在这种情况下(而且,我认为仅在这种情况下)a goto直接与问题域中的概念相对应,从一个状态过渡到指定的另一个状态,其中当前状态由当前执行代码块表示。

另一方面,也可以使用循环内的开关语句实现显式有限状态机。这具有一个优势,即每个状态在代码中的同一位置启动,例如,这对于调试可能很有用。

在相当现代的语言中,goto的主要用途(一种支持/else and循环的语言)是模拟语言缺少的控制流构造。

当然,这取决于编程语言。主要原因 goto 引起争议的是因为它的不良影响是当编译器让您过于自由地使用它时会出现。例如,如果您可以使用问题,可能会出现问题 goto 以这样的方式,您现在可以访问一个非初始化的变量,或更糟地跳入另一种方法并弄乱呼叫堆栈。编译器不允许非敏感控制流量是责任。

Java试图通过不称呼来“解决”这个问题 goto 完全。但是,Java让您使用 return 内部 finally 阻止,因此导致异常被无意中吞咽。仍然存在同样的问题:编译器没有完成工作。去除 goto 从该语言尚未修复它。

在C#中, goto 像安全 break, continue, try/catch/finallyreturn. 。它不允许您使用非初始化的变量,也不会让您跳出最后一个块,等等。编译器会抱怨。这是因为它解决了 真实的 问题,就像我说的荒谬控制流一样。 goto 不会神奇地取消确定分析分析和其他合理的编译器检查。

是的。当您的循环深处几个层次时, goto 是个 只要 优雅地从内部循环中脱颖而出的方式。另一个选项是设置标志,如果该标志满足条件。这确实很丑陋,而且很容易出错。在这些情况下, goto 更好。

当然,Java的标签 break 语句做同样的事情,但不允许您跳到代码中的任意点,该点可以整齐地解决问题,而不允许使问题允许 goto 邪恶的。

大部分的沮丧都形成了一种“宗教”,这是一种创造的aroud上帝djikstra,在60年代初期令人信服的是它不加区分的力量:

  • 跳入任何代码块
    • 函数未从开始执行
    • 循环从一开始就没有执行
    • 跳过变量初始化
  • 在没有任何可能清理的情况下跳出任何代码块。

这与 goto 现代语言的陈述,其存在仅仅是由于支持语言提供的代码结构的创建。

特别是上面的第一个要点是允许的,第二个要清洁(如果您 goto 从一个街区中正确地将堆栈切开,所有适当的破坏者都称为)

您可以参考 这个答案 要了解如何甚至不使用goto的代码是不可读的。问题本身不是goto本身,而是对它的不良使用。

我可以在不使用的情况下编写整个程序 if, , 只是 for。当然,它的阅读效果不佳,外观笨拙且不必要地复杂。

但是问题不是 for. 。是我。

break, continue, throw, bool needed=true; while(needed) {...}, 等等等 化妆舞会 goto 为了逃离迪克斯特里安狂热者的小脚尖,在现代拉甘斯发明的-50年后,仍然想要他们的囚犯。他们忘记了Djikstra在说什么,他们只记得他的笔记的头衔(被认为有害,甚至不是他的onw头衔:编辑被更改),责备和bash,bash,bash和责备,责备所有4个有4个字母顺序。

是2011年:是时候了解 goto 已经注意到要处理 GOTO 声明Djikstra令人信服。

只要它是局部功能,在这里或那里的奇数goto很少会损害可读性。它通常通过提请注意以下事实来使其受益,即此代码中发生了一些不寻常的事情,需要使用某种罕见的控制结构。

如果(本地)GOTO极大地损害了可读性,则通常是一个迹象表明包含goto的功能变得过于复杂。

我放入的最后一个C代码是构建一对互锁循环。它不符合“可接受” Goto使用的正常定义,但是该功能最终变得明显更小,更清晰。为了避免,goto需要特别混乱的侵犯干燥的行为。

我认为整个问题一直是吠叫错误的树。

因为我对我来说似乎并没有问题,而是经常是实际罪的症状:意大利面条代码。

如果goto导致流量控制线的重大交叉,那么这是不好的。如果它越过流量控制线,那将是无害的。在我们之间的灰色区域中,我们有诸如Loop Bailouts之类的东西,仍然有一些语言尚未添加涵盖所有合法灰色案例的构造。

我发现自己在多年内实际使用它的唯一情况是循环中的决策点位于循环的中间。您剩下的要么重复的代码,标志或goto。我发现goto解决方案是三个中最好的。这里没有流量控制线的交叉,这是无害的。

是的,可以使用goto来受益于开发人员的体验:http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

但是,就像任何强大的工具(指针,多继承等)一样,必须使用它进行纪律处分。链接中提供的示例使用PHP,该示例将goto构造的使用限制为相同的函数/方法,并禁用跳入新的控制块的能力(例如,循环,开关语句等)。

取决于语言。例如,它仍然被广泛用于COBOL编程。我还使用Barionet 50设备工作,该设备的固件编程语言是一种早期的基本方言,当然需要您使用goto。

我会说不。如果您发现需要使用goto,我敢打赌,需要重新设计代码。

goto 将传统汇编代码移植到C。在第一案中,使用指令转换为C,可能很有用 goto 作为组装商的替代者 branch 指示,可以实现非常快速的移植。

我会辩护。应始终将它们替换为更具体的工具,以解决该问题用于解决的问题(除非您的语言不可用)。例如,中断语句和异常解决了以前解决的问题,循环逃脱和错误处理。

许可以下: CC-BY-SA归因
scroll top