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




我正通过xkcd随机播放,并看到了这个(如果几年前还读过一些关于它们的否定文字):
是什么真的错了吗?那么为什么在C ++中甚至可以使用goto?

为什么不应该使用它们?

评论

我认为这个问题没有任何问题。因此+1以抵消反对票。

这个关于该主题的博客值得一读:blog.smartbear.com/development/…

避免使用GOTO的最佳理由以xkcd卡通为例:如果使用GOTO,很可能会受到恐龙的攻击。<​​br />
在另一篇文章中使用相同图形的答案。

#1 楼

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

过去,编程语言没有while循环,if语句等,并且程序员使用goto来构成其程序的逻辑。这会导致无法维护的混乱。这就是CS诸神创建方法,条件和循环的原因。结构化编程当时是一场革命。

goto在某些地方很合适,例如从嵌套循环中跳出来。

评论


跳出嵌套循环是我使用过goto语句的唯一实例。即使那样,我也将代码重构为在可能的情况下尽早返回。

–查理盐
2010年8月19日,0:14



+1表示在极少数情况下goto仍具有目的。

–马特·戴维斯(Matt Davis)
2010年8月19日在1:25

我知道这是一篇过时的文章,但我想我会为goto再增加一个用途。在SQR中,goto通常用作循环中的“继续”。许多数据库语言都没有在语言中继续使用,因此将goto放在循环的末尾,并在需要“继续”时调用它。

–brw59
16年6月19日在3:40

说得更准确些,因为如果使用不当,它们很容易导致意大利面条代码。有时,实际上它是最干净,最干燥的处理方式,尤其是在不关注结构化编程的语言中,正如我在尝试使循环在T-SQL中继续时刚刚发现的那样。

–登齐洛
19年2月19日在16:35



可以使用return代替goto跳出嵌套循环。例如,将嵌套循环提取到新函数中,并在满足触发goto的条件时从那里返回。我只看到goto仅用于获得额外的性能

– mljrg
19-10-4在9:57

#2 楼

如果正确使用goto,则没有任何问题。之所以称其为“禁忌”,是因为在C语言的早期,程序员(通常来自汇编背景)会使用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
2012年5月12日下午6:21

@SasQ:编译器负责确保为goto生成的实际“ jmp”指令之前带有摆脱内部作用域变量所需的任何代码。

–超级猫
2012年5月13日20:31

goto可以在函数之间跳转并不是真的。 C为此具有longjmp(),而C ++具有异常。

– Celticminstrel
16年7月19日在23:53

关于您声称“ goto也可以用于从一个函数跳到另一个函数而无需进行函数调用”的说法:**您声称可以使用goto来“从一个函数跳至另一个函数而无需进行函数调用”是错误的,因为在这里和这里解释,也可以在@celticminstrel的正上方看到注释。

–特雷弗·博伊德·史密斯
18年1月1日在18:05

@TrevorBoydSmith-是的,我一定一直在考虑longjmp(相同的问题概念,不同的界面)。固定。

– bta
18 Mar 1 '18 at 23:18

#3 楼

goto本身没有任何问题。它是编程中非常有用的构造,并具有许多有效用法。想到的最好的方法是C程序中的结构化资源释放。

goto出错的地方是当它们被滥用时。滥用gotos可能会导致完全无法阅读和无法维护的代码。

#4 楼

1968年,埃德斯·迪克斯特拉(Edsger Dijkstra)写了一封著名的信给ACM通讯编辑,认为这是有害的,他提出了使用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与(计算)恐龙灭绝了

– Gerry Coll
2010年8月19日,0:31

@Gerry:那是一个好人。我没想到。

–肯·布鲁姆
2010年8月19日,0:38



实际上,通过他使用的goto(进入某种子程序),猛禽应该攻击他。

–肯·布鲁姆
2010年8月19日在13:39

我发现DIjkstra的解释(及其直接后果)是不使用goto的真正原因,而不仅仅是每个人都以为的“非结构化代码”。还有更多的含义,您应该正确地提及它。

– Vultrao
15年1月20日在13:25

Java没有goto命令,但具有相同目的的中断

–大卫·杜美琪
2015年10月7日在7:34

#5 楼

您是否用谷歌搜索了这个问题?

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

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

#6 楼

在C ++中是可能的,因为在C中是可能的。无论您是否应该使用它,都是长期的宗教战争。
C ++的设计目标是在野外使用99%的C程序应该使用C ++中的相同功能进行编译和运行。包括goto是实现该目标的一部分工作。

评论


显然,问题的作者并不知道为什么C中也可以使用“ goto”。

–dionyziz
2010年8月19日,0:30

C ++不是C的超集。

–user142019
2010年8月19日,0:46

并非如此,但是C ++的最初目标(显然是棘手的问题)之一就是与C的强大兼容性。而且我仍然不为您感到沮丧。

– Nikolai Fetissov
2010年8月19日在1:08



@kon为公平起见,您必须编写真正古老的C代码以使其在C ++中无效,mod俄语备份:-)

– Anycorn
2010年8月19日在3:11



嘿,谢谢,我不知道附近有俄罗斯暴民:)

– Nikolai Fetissov
2010年8月19日,3:15