可能的重复:为什么使用goto不好?GOTO仍然被认为是有害的?
我正通过xkcd随机播放,并看到了这个(如果几年前还读过一些关于它们的否定文字):
是什么真的错了吗?那么为什么在C ++中甚至可以使用goto?
为什么不应该使用它们?
#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
评论
我认为这个问题没有任何问题。因此+1以抵消反对票。这个关于该主题的博客值得一读:blog.smartbear.com/development/…
避免使用GOTO的最佳理由以xkcd卡通为例:如果使用GOTO,很可能会受到恐龙的攻击。<br />
在另一篇文章中使用相同图形的答案。