在这个主题中,我们看一下gotoC或C++ 的良好用法示例.它的灵感来自人们投票的答案,因为他们认为我在开玩笑.
摘要(标签从原始标签更改为使意图更清晰):
infinite_loop:
// code goes here
goto infinite_loop;
Run Code Online (Sandbox Code Playgroud)
为什么它比替代品更好:
goto是导致无条件分支的语言构造.替代方案取决于使用支持条件分支的结构,具有退化的始终为真的条件.breakS(尽管它仍然可能无原则黑客模拟
continue与早期goto).规则:
让我们看看我们是否可以像成年人一样谈论这个问题.
编辑
这个问题现在好了.它产生了一些高质量的答案.感谢大家,尤其是那些认真对待我的小循环示例的人.大多数怀疑论者都担心缺乏范围.正如@quinmars在评论中指出的那样,你总是可以在循环体上放置大括号.我顺便注意到for(;;)并且while(true)也没有给你免费的大括号(并且省略它们会导致烦恼的错误).无论如何,我不会浪费任何更多的脑力这个小事-我可以用无害的习惯生活for(;;)和while(true)(一样好,如果我想继续我的工作).
考虑到其他反应,我发现许多人认为goto你总是需要以另一种方式重写.当然,你可以goto通过引入一个循环,一个额外的标志,一堆嵌套的ifs或其他什么来避免,但为什么不考虑是否goto可能是这项工作的最佳工具?换句话说,人们准备忍受多少丑陋以避免使用内置语言功能达到预期目的?我的看法是,即使添加一面旗帜,也要付出太高的代价.我喜欢我的变量来表示问题或解决方案域中的事物.'唯一要避免goto'不削减它.
我会接受第一个给出C模式分支到清理块的答案.国际海事组织,这是goto所有已发布答案的最强情况,当然,如果你通过一个仇恨必须通过避免它的扭曲来衡量它.
Gre*_*ers 87
这是我听说人们使用的一个技巧.我从来没有在野外见过它.它只适用于C,因为C++有RAII来更加惯用.
void foo()
{
if (!doA())
goto exit;
if (!doB())
goto cleanupA;
if (!doC())
goto cleanupB;
/* everything has succeeded */
return;
cleanupB:
undoB();
cleanupA:
undoA();
exit:
return;
}
Run Code Online (Sandbox Code Playgroud)
Pau*_*han 85
C中GOTO的经典需求如下
for ...
for ...
if(breakout_condition)
goto final;
final:
Run Code Online (Sandbox Code Playgroud)
没有goto,没有直接的方法来突破嵌套循环.
fiz*_*zer 32
这是我的非愚蠢的例子(来自Stevens APITUE),用于Unix系统调用,可能会被信号中断.
restart:
if (system_call() == -1) {
if (errno == EINTR) goto restart;
// handle real errors
}
Run Code Online (Sandbox Code Playgroud)
替代方案是简并循环.这个版本读起来像英语"如果系统调用被信号中断,重新启动它".
Mit*_*eat 14
如果Duff的设备不需要goto,那么你也不应该!;)
void dsend(int count) {
int n;
if (!count) return;
n = (count + 7) / 8;
switch (count % 8) {
case 0: do { puts("case 0");
case 7: puts("case 7");
case 6: puts("case 6");
case 5: puts("case 5");
case 4: puts("case 4");
case 3: puts("case 3");
case 2: puts("case 2");
case 1: puts("case 1");
} while (--n > 0);
}
}
Run Code Online (Sandbox Code Playgroud)
维基百科条目上面的代码.
Bri*_*ndy 12
我一般都没有反对任何东西,但我可以想到几个原因,为什么你不想像你提到的那样将它们用于循环:
eph*_*ent 12
很普通的.
do_stuff(thingy) {
lock(thingy);
foo;
if (foo failed) {
status = -EFOO;
goto OUT;
}
bar;
if (bar failed) {
status = -EBAR;
goto OUT;
}
do_stuff_to(thingy);
OUT:
unlock(thingy);
return status;
}
Run Code Online (Sandbox Code Playgroud)
我曾经使用过的唯一一个例子goto就是向前跳,通常是用块跳,而不是用块.这避免了滥用do{}while(0)和其他增加嵌套的构造,同时仍然保持可读的结构化代码.
使用goto的一个好地方是可以在几个点中止的程序,每个点都需要不同级别的清理.Gotophobes总是可以用结构化代码和一系列测试替换gotos,但我认为这更简单,因为它消除了过多的缩进:
if (!openDataFile()) goto quit; if (!getDataFromFile()) goto closeFileAndQuit; if (!allocateSomeResources) goto freeResourcesAndQuit; // Do more work here.... freeResourcesAndQuit: // free resources closeFileAndQuit: // close file quit: // quit!
@ fizzer.myopenid.com:您发布的代码段等效于以下内容:
while (system_call() == -1)
{
if (errno != EINTR)
{
// handle real errors
break;
}
}
Run Code Online (Sandbox Code Playgroud)
我绝对喜欢这种形式.
尽管随着时间的推移我已经开始讨厌这种模式,但它已经融入了COM编程中.
#define IfFailGo(x) {hr = (x); if (FAILED(hr)) goto Error}
...
HRESULT SomeMethod(IFoo* pFoo) {
HRESULT hr = S_OK;
IfFailGo( pFoo->PerformAction() );
IfFailGo( pFoo->SomeOtherAction() );
Error:
return hr;
}
Run Code Online (Sandbox Code Playgroud)
这是一个很好的转到的例子:
// No Code
Run Code Online (Sandbox Code Playgroud)