可能的重复: 为什么使用goto不好? GOTO仍然被认为有害?

我在浏览xkcd时看到了这个(如果几年前也读过一些关于他们的负面文章): 它到底有什么问题?那么为什么goto在c++中是可能的呢?

为什么我不应该使用它们?


“去”本身并没有什么错。它在编程中是一个非常有用的结构,有很多有效的用途。我能想到的最好的方法是在C程序中释放结构化资源。

当goto被滥用时,它就会出问题。滥用gotos会导致代码完全不可读和不可维护。


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

c++的一个设计目标是,99%左右的C程序在编译和运行时应该具有与c++相同的功能。包括goto是实现这一目标的努力的一部分。


你知道这个问题吗?

反后藤运动的创始人是Edsger Dijskstra和他的传奇之作《后藤有害》。

你可以登录http://en.wikipedia.org/wiki/GOTO开始学习


因为它们会导致意大利面条式的代码。

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

这就是为什么CS之神创造了方法、条件和循环。结构化编程在当时是一场革命。

Gotos在一些地方是合适的,比如跳出嵌套循环。


In 1968, Edsger Dijkstra wrote a famous letter to the editor of Communications of the ACM GOTO is considered harmful in which he laid out the case for structured programming with while loops and if...then...else conditionals. When GOTO is used to substitute for these control structures, the result is very often spaghetti code. Pretty much every programming language in use to day is a structured programming language, and use of GOTOs has been pretty much eliminated. In fact, Java, Scala, Ruby, and Python don't have a goto command at all.

C, C++ and Perl still do have a GOTO command, and there are situations (in C particularly) where a GOTO is useful, for example a break statement that exits multiple loops, or as a way of concentrating cleanup code in a single place in a function even when there are multiple ways to terminate the function (e.g. by returning error codes at multiple points in the progress of a function). But generally its use should be restricted to specific design patterns that call for it in a controlled and recognized way.

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

XKCD漫画是一个关于“当某些特定的设计模式因GOTO的使用而得到极大帮助时,GOTO是否总是被认为是有害的?”


如果使用得当,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来实现子程序是它被滥用的主要方式。这就产生了所谓的“意大利面条代码”,使其难以阅读和维护。