【问题标题】:What is wrong with using goto? [duplicate]使用 goto 有什么问题? [复制]
【发布时间】:2011-03-31 20:53:30
【问题描述】:

可能的重复:
Why is it bad to use goto?
GOTO still considered harmful?

我正在通过 xkcd 乱搞,看到了这个(如果几年前还读过一些关于他们的负面文本):

它实际上有什么问题?那么为什么在 C++ 中甚至可以使用 goto 呢?

为什么我应该使用它们?

【问题讨论】:

  • 我看不出这个问题有什么问题。所以 +1 来抵消反对票。
  • 这篇关于该主题的博客值得一读:blog.smartbear.com/development/…
  • 避免 GOTO 的最佳理由是 xkcd 动画片:如果你使用 GOTO,你很可能会被恐龙袭击。
  • The answer 在另一个帖子中使用相同的图形。

标签: c++ goto


【解决方案1】:

因为它们通向spaghetti code

过去,编程语言没有while循环、if语句等,程序员使用goto来组成程序逻辑。它会导致无法维护的混乱。

这就是 CS 之神创造方法、条件和循环的原因。 Structured 编程在当时是一场革命。

goto 适用于一些地方,例如跳出嵌套循环。

【讨论】:

  • 跳出嵌套循环是我使用 goto 语句的 only 实例。即便如此,我还是重构了我的代码,以便尽可能早点返回。
  • +1 表示承认 goto 在极少数情况下仍有目的。
  • 我知道这是一篇旧帖子,但我想我会为 goto 添加更多用途。在 SQR 中,goto 通常用作循环中的“继续”。许多数据库语言在语言中没有 continue ,因此它们在循环末尾放置一个 goto 并在需要“继续”时调用它。
  • 更准确地说,因为如果不明智地使用它们可以很容易导致意大利面条代码。有时它实际上是最干净、最干燥的做事方式,尤其是在不关注结构化编程的语言中,正如我刚刚在 T-SQL 中尝试使循环继续时发现的那样。
  • 可以使用return 代替goto 跳出嵌套循环。例如,将嵌套循环提取到一个新函数中,并在满足触发goto 的条件时从那里返回。我只看到goto 仅用于获得额外的性能
【解决方案2】:

如果使用得当,goto 没有任何问题。它之所以成为“禁忌”是因为在 C 语言的早期,程序员(通常来自汇编背景)会使用goto 来创建难以置信的难以理解的代码。

大多数时候,你可以不用goto 也能过得很好。但是,在少数情况下,goto 可能很有用。最好的例子是这样的情况:

for (i = 0; i < 1000; i++) {
    for (j = 0; j < 1000; j++) {
        for (k = 0; k < 1000; k++) {
            ...
            if (condition)
                goto break_out;
            ....
        }
    }
}
break_out:

使用goto 跳出深度嵌套的循环通常比使用条件变量并在每个级别上检查它更干净。

使用goto实现子程序是其被滥用的主要方式。这会产生所谓的“意大利面条式代码”,阅读和维护起来非常困难。

【讨论】:

  • 如果栈上构造了一些自动对象,这些对象在循环内部是局部的怎么办? Goto 将跳转到其他地方,跳过块的末端,这些对象的析构函数被调用。正确的?在大多数情况下,它不会做任何坏事。但在某些情况下它会这样做,包括丢失用户数据等。
  • @SasQ:编译器负责确保为goto 生成的实际“jmp”指令前面是删除内部范围变量所需的任何代码。
  • goto 不能在函数之间跳转。 C 有longjmp(),C++ 有例外。
  • 关于您声称“goto 也可用于在不进行函数调用的情况下从一个函数跳转到另一个函数”:**your claim that you can use goto to "jump from one function into another without making a function call" is wrong as explained by herehere,还可以直接查看上面@celticminstrel 的评论。
  • @TrevorBoydSmith- 你说得对,我一定一直在考虑longjmp(同样有问题的概念,不同的界面)。固定。
【解决方案3】:

goto 本身并没有什么问题。它在编程中是一个非常有用的结构,并且有许多有效的用途。想到的最好的方法是 C 程序中的结构化资源释放。

goto 出错的地方是当他们被滥用时。滥用 goto 会导致代码完全不可读和不可维护。

【讨论】:

    【解决方案4】:

    1968 年,Edsger DijkstraCommunications of the ACM GOTO is considered harmful 的编辑写了一封著名的信,他在信中阐述了使用 while 循环的结构化编程的案例> 和 if...then...else 条件句。当使用 GOTO 替代这些控制结构时,结果通常是spaghetti code。当今使用的几乎所有编程语言都是结构化编程语言,而 GOTO 的使用几乎已被淘汰。事实上,Java、Scala、Ruby 和 Python 根本没有goto 命令。

    C、C++ 和 Perl 仍然有 GOTO 命令,并且在某些情况下(尤其是在 C 中)GOTO is useful,例如退出多个循环的 break 语句,或者作为将清理代码集中在即使有多种方法可以终止函数(例如,通过在函数执行过程中的多个点返回错误代码),函数中的单个位置也是如此。但一般来说,它的使用应仅限于特定的设计模式,这些设计模式以受控和公认的方式需要它。

    (在 C++ 中,最好使用 RAII 或 ScopeGuard (more) 而不是使用 GOTO 进行清理。但 GOTO 是 frequently used idiom in the Linux kernel (another source),这是惯用 C 代码的一个很好的例子。)

    XKCD 漫画是关于“当 GOTO 的使用对某些特定设计模式有很大帮助时,是否应该始终认为 GOTO 是有害的?”这个问题的笑话?

    【讨论】:

    • GOTO 与(计算)恐龙一起出局
    • @Gerry:这很好。我没有想到。
    • 实际上,通过他使用的gotogoto 某种子程序),猛禽应该攻击他。
    • 我发现 DIjkstra 解释(及其直接后果)是不使用 goto 的真正原因,而不仅仅是每个人都认为的“非结构化代码”。还有更多的含义,你说得对。
    • Java 没有goto 命令,但有一个break 用于相同目的
    【解决方案5】:

    你用谷歌搜索了这个问题吗?

    反 goto 运动的创始人是 Edsger Dijskstra,他的传奇“Goto 被认为是有害的”

    要开始,您可以转到(哈哈!)http://en.wikipedia.org/wiki/GOTO

    【讨论】:

    • 具有讽刺意味的是,他实际上对 GOTO 的容忍度远远超过了今天的程序员。对于 Djikstra,向前 GOTO 是可以的,向后 GOTO 和 GOTO 进入循环内部是不行的。
    【解决方案6】:

    这在 C++ 中是可能的,因为它在 C 中是可能的。你是否应该使用它是长期的宗教战争。

    C++ 的设计目标是 99% 左右的 C 程序应该在 C++ 中以相同的功能编译和运行。包括goto 是实现该目标的一部分。

    【讨论】:

    • 显然问题的作者不知道为什么“goto”也可以在 C 中使用。
    • C++ 不是 C 的超集。
    • 不是,但 C++ 的最初目标之一(显然也是祸根)是与 C 的强兼容性。我仍然不明白你为什么这么不高兴。
    • @kon 公平地说,您必须编写非常古老的 C 代码才能使其在 C++ 中无效,支持 mod russians :-)
    • 嘿,谢谢,我不知道这里有俄罗斯暴徒:)
    猜你喜欢
    • 1970-01-01
    • 2012-07-16
    • 2021-11-20
    • 2019-04-11
    • 2016-04-15
    • 2016-03-20
    • 2020-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多