使用goto有什么问题?

106 c++ goto

可能重复:
为什么使用goto不好?
GOTO仍被视为有害吗?

我通过xkcd进行了调整,看到了这个(几年前还读了一些关于它们的负面文章):
你的慢连接很糟糕,得到一个更快的看到这个图像
这究竟是什么问题?为什么goto甚至可以在C++中使用呢?

我为什么使用它们?

Byr*_*ock 97

因为它们会导致意大利面条代码.

在过去,编程语言没有while()if()等,程序员使用goto来构成程序的逻辑.它导致了一个难以维护的混乱局面.

这就是CS众神创造函数条件和循环的原因.结构化编程在当时是一场革命.

goto适用于少数几个地方,例如跳出嵌套循环

  • 确认"goto"在极少数情况下仍有目的的+1. (69认同)
  • 跳出嵌套循环是我使用goto语句的*only*实例.即使这样,我也会重构我的代码,以便尽可能早地返回. (11认同)
  • 我知道这是一个旧帖子,但我想我会为goto添加一个用途.在SQR中,goto通常用作循环中的"continue".许多数据库语言没有继续使用该语言,所以他们在循环结束时放置一个goto并在需要"继续"时调用它. (3认同)
  • 可以使用“return”代替“goto”来跳出嵌套循环。例如,将嵌套循环提取到一个新函数中,并在满足触发“goto”的条件时从该函数返回。我只看到使用“goto”只是为了获得额外的性能 (3认同)
  • 更准确地说,因为如果不明智地使用它们*可以*很容易导致意大利面条式代码。有时它实际上是最干净、最干的做事方式,尤其是在不关注结构化编程的语言中,正如我刚刚在 T-SQL 中尝试使循环继续时发现的那样。 (2认同)
  • “过去,编程语言没有...... if 语句”错误。就像大多数汇编语言一样,Basic 总是有 if 语句。(尽管“if”可能是“如果为零则跳转”)至于在嵌套循环中使用 goto ;我个人认为,如果你想跳出嵌套循环;然后你创建一个函数并从中返回。 (2认同)

bta*_*bta 62

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:
Run Code Online (Sandbox Code Playgroud)

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

使用goto来实现子程序是被滥用的主要途径.这产生了所谓的"意大利面条代码",其不必要地难以阅读和维护.

  • @SasQ:编译器负责确保为`goto`生成的实际"jmp"指令前面是摆脱内部范围变量所需的任何代码. (12认同)
  • 如果在堆栈上构建了一些自动对象,这些对象在循环内是局部的,该怎么办?Goto将跳转到其他位置,跳过块的末尾,这些对象的析构函数被调用.对?在大多数情况下,它不会做任何坏事.但有些情况会发生,包括丢失用户的数据等. (4认同)
  • `goto`在函数之间跳转是不正确的.C有`longjmp()`,而C++有例外. (3认同)
  • 如果您需要一个“O(N^3)”循环,也许“goto”是您最不用担心的。 (2认同)

Jar*_*Par 31

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

当goto出现问题时,他们会被滥用.滥用gotos可能导致完全不可读和无法维护的代码.


Ken*_*oom 24

1968年,Edsger DijkstraACM GOTO的编辑写了一封着名的信,被认为是有害的,他用while循环if ...... then ... else条件为结构化编程奠定了基础.当GOTO用于替代这些控制结构时,结果通常是意大利面条代码.几乎每种使用的编程语言都是结构化编程语言,并且几乎消除了GOTO的使用.事实上,Java,Scala,Ruby和Python根本没有goto命令.

C,C++和Perl仍然有一个GOTO命令,有些情况(特别是在C中)GOTO很有用,例如一个退出多个循环的break语句,或者作为一种将清理代码集中在一个地方的方法即使有多种方法来终止函数(例如,通过在函数进程中的多个点返回错误代码),也可以使用函数.但一般来说,它的使用应限于以受控和公认的方式要求它的特定设计模式.

(在C++中,最好使用RAII或ScopeGuard (更多)而不是使用GOTO进行清理.但是GOTO是Linux内核中常用的习惯用法(另一个来源),这是惯用C代码的一个很好的例子.)

XKCD漫画是一个关于"如果某些特定的设计模式在使用时受到极大帮助,GOTO总是被视为有害的问题"的笑话吗?

  • GOTO和恐龙(计算)一起出去了 (5认同)
  • 我发现 DIjkstra 的解释(及其直接后果)是不使用 goto 的真正原因,而不仅仅是每个人都认为的“非结构化代码”。还有更多的含义,你提到它是对的。 (2认同)

Joh*_*ith 8

你有问题吗?

反goto运动的创始人是Edsger Dijskstra,他的传奇故事是"Goto Considered Harmful"

为了帮助您入门,您可以转到(哈哈!)http://en.wikipedia.org/wiki/GOTO

  • 讽刺的是,他实际上比今天的程序员更能容忍 GOTO。对于 Djikstra 来说,向前 GOTO 是可以的,向后 GOTO 和 GOTO 进入循环内部就不行了。 (2认同)

Nik*_*sov 6

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

  • 事实并非如此,但C++最初的目标之一(显然是诅咒)与C的强大兼容性.我仍然没有得到你如此不安的东西. (7认同)
  • C++不是**不是C的超集. (4认同)
  • 显然,问题的作者并不知道为什么C中也可以使用“ goto”。 (2认同)
  • @kon 公平地说,你必须编写真正古老风格的 C 代码以使其在 C++ 中无效,mod Russians 支持:-) (2认同)