为什么和何时应该在C / C++中使用goto?

6
我知道很多人会问为什么不能使用goto,为什么goto是不好的编程习惯,为什么goto是由恶魔创造的,为什么那些打goto的人的手指应该被割掉等等问题...在许多回答中这个问题,甚至在wikipedia上都可以找到支持/反对goto的理由。即使Stackoverflow也有一个goto标签 :) 但是,显然,goto被认为是有效的命令,否则你的编译器/解释器就不知道该怎么做了。即使在C/C++中也可以使用goto,并且该语言甚至拥有正式的ISO规范。
因此,可能存在一些情况,只有使用goto才能完成某些任务。那么,在C / C ++中何时应该使用goto
编辑:
只是为了确保:
1-这个问题不需要辩论。它应该是可以回答的:给出一个或多个只有goto是唯一解决方案的情况,或者声明否,总是可以避免使用goto。当然,我不是唯一可以决定是否关闭它的人,但我认为“太广泛,要求辩论等”不是关闭它的理由。
2-可能存在一些情况,其中goto可以使代码更清晰、更快等。我不想要那些。我想知道是否存在一种情况,其中goto是唯一的解决方案(不,它不是那个“给出goto的好例子”的重复问题)。

3 - 如果downvote是有道理的,我会微笑着接受任何downvote。但我非常确定这个问题有答案,并且已经对该主题进行了先前的研究。仅仅因为使用了那个以“G”开头的四个字母禁忌词而进行downvoting...抱歉...


2
这个问题对于 Stack Overflow 的问答格式来说过于主观。答案大多是关于风格的问题,并且非常依赖于具体情况。 - Dave
1
不要给我意见。我需要一个具体的案例,只有使用goto才能解决某些情况。我不想听关于速度、让你的代码更加晦涩的意见。 - woliveirajr
2
那么不行,没有一种情况下goto唯一的选择。您可以使用ifforswitch执行任何分支任务,但在某些非常罕见的情况下,这可能导致代码不太易读。 - Dave
1
@woliveirajr - 很抱歉,您的问题被标记为重复。它并不是一个重复问题(或者至少不是指定问题的重复)。您正在询问一个只有goto是唯一可能解决方案的场景,这与goto是一个好的解决方案的场景完全不同。 - Andrew Cottrell
3
关于你更新的评论,说实话:无论问题意图如何,你都会得到大多数基于个人观点的答案,这就是为什么我投票将其关闭为过于宽泛(我的投票被卷入了重复投票中,但没关系)。现在你已经从几个来源得到了答案:没有这种情况。现在你能期望的最好结果是,每一种可能性都被提出并用反例打破,但这不是建设性的。 - Dave
显示剩余7条评论
4个回答

10

没有任何情况下使用goto是绝对必要的:如果您真的想避免它,您总是可以这样做,但仅出于纯粹的意识形态原因而这样做是错误的。

例如,我的一个朋友编写了一个小波变换函数,其中(大约)有15个嵌套循环。如果这些循环中出现错误,他使用了一个goto语句来跳转到清理代码块,以便在函数的return语句之前进行清理。如果没有使用goto,实现相同的效果将涉及设置标志并在每个循环级别上测试它,这将使他的代码难以阅读。在这种情况下,goto是正确的选择。


1
告诉你的朋友,15个嵌套循环太多了... 大约要减少13个。 - Dave
1
也许17年前他没有意识到这一点。 - Emmet
1
我的观点是,在那种情况下是否选择了goto是无关紧要的:情况本身就很糟糕。此外,这是一个可能更好的选择的示例。问题在于寻找它是唯一选项的情况。 - Dave
2
这些情况不存在,因为该语言在没有“goto”结构的情况下是图灵完备的。因此,在我看来,唯一合理的答案是陈述这个事实并举出一个例子,即使它可以避免,这正是我所做的。如果你的观点与问题的实质问题有关,而不是针对一个无关紧要的细节的攻击,那么你的评论并没有很好地传达这一点。 - Emmet
1
如果您想了解我的完整意见,请查看主问题评论线程上的我的评论。如果您在答案中更新图灵完备性论证(我建议删除它在特定情况下更可取的无关示例),我对此没有异议。 - Dave
3
我对我的回答感到满意,谢谢。 - Emmet

6

最新的MISRA标准现在允许使用goto语句。

一个很好的例子是当你有一个大型程序,有很多退出点时,使用goto语句是有意义的。你可以有许多return语句(不好),也可以用“结构化编程”条件语句使代码复杂化(也不好),或者使用“goto Done;”将程序发送到一组结束语句之前返回。

MISRA标准基本上允许在这些情况下使用goto语句。我认为“只向下”是他们的一个标准。


我无法理解goto语句比多个返回语句更好的原因。 - jrok
1
https://dev59.com/F2Qn5IYBdhLWcg3wAjIY#17177315 - Jiminion
4
通常情况下,当你有一段清理代码,如果你使用多个返回语句会导致重复时,你可以使用这段代码。 - Paul R
2
你把MISRA当作控制所有编程的圣经一样来引用。 - Dan
关于MISRA,有很多我不喜欢的地方。但它是一个试图解释决策背后原理的标准。我发现他们在与早期标准相比,放弃了禁止使用goto(以及'break',除了在switch中使用,还有'continue')这一点非常重要。MISRA是一个C语言标准,所以它只适用于C而不是C++(我认为)。 - Jiminion
显示剩余2条评论

5

我使用“goto”的唯一原因是在函数需要进行一些常见的清理并返回错误条件时。 “goto”语句的目标位于函数末尾附近,“正常”的返回在标签之前。


3
好的!如果您在返回之前需要进行任何最终处理,您可以将所有处理放在一个地方。代码中出现的多个“goto Done”并不会让人困惑或混乱,因为很清楚正在发生什么。 - Jiminion

3
这里有一个只能使用goto才能解决的示例: https://dev59.com/mHVC5IYBdhLWcg3wlyMo#245801 如果您有多个嵌套的for循环,从内部循环中跳出所有循环的唯一方法是使用goto语句(因为与其他某些语言不同,C中的break关键字不支持用于跳出多层嵌套的参数)。

3
即使如此,这也不需要使用goto语句。你还可以使用变量作为标记来表示循环已经结束,并在每个级别上单独跳出循环。goto简单地提供了一种更易读且潜在更快的选择(虽然我怀疑现代编译器是否真的更快)。使用一个小函数和return语句(如该答案的评论中建议的)也是一个很好的选项,这将编译成几乎与使用goto相同的结果。 - Dave
2
是的,从功能上讲可能可以工作,但我认为你错过了重点。如果你想立即跳出所有循环,那么只有 goto 才能起作用。在你的例子中,你在每个嵌套层级上都添加了一个变量比较检查,这与立即跳出不同。 - Andrew Cottrell
1
第二个选项(一个带返回值的单独函数)将会立即退出。我同意在某些情况下,goto更合适,但你不可能声称它是唯一的方法。 - Dave
1
我绝对声称这是立即跳出嵌套的“for”循环并继续执行该函数中后续代码的唯一方法。我不是说这是最佳实践,也不是说循环等不能被重写以另一种方式实现目标。我是说这是在不重写周围代码的情况下实现特定目标的唯一方法。 - Andrew Cottrell
当然,按照这个标准,你可以认为所有使用goto的情况都是“只有goto才能工作”的情况,因为goto唯一一种可以立即跳转到函数中任意指定位置的方法。从函数中删除goto总是涉及重写周围的代码。 - ruakh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接