C++ 做 {...} 而(假)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2314066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
do {...} while(false)
提问by Mr. Boy
I was looking at some code by an individual and noticed he seems to have a pattern in his functions:
我正在查看一个人的一些代码,并注意到他的函数中似乎有一个模式:
<return-type> function(<params>)
{
<initialization>
do
{
<main code for function>
}
while(false);
<tidy-up & return>
}
It's not bad, more peculiar (the actual code is fairly neat and unsurprising). It's not something I've seen before and I wondered if anyone can think of any logic behind it - background in a different language perhaps?
这还不错,更奇特(实际代码相当整洁且不足为奇)。这不是我以前见过的东西,我想知道是否有人能想到它背后的任何逻辑——也许是不同语言的背景?
回答by Thomas Eding
You can break
out of do{...}while(false)
.
你可以break
出do{...}while(false)
。
回答by Ben Voigt
A lot of people point out that it's often used with break as an awkward way of writing "goto". That's probably true if it's written directly in the function.
很多人指出,它经常与 break 一起使用,作为写“goto”的尴尬方式。如果它直接写在函数中,那可能是正确的。
In a macro, OTOH, do { something; } while (false)
is a convenient way to FORCE a semicolon after the macro invocation, absolutely no other token is allowed to follow.
在宏中,OTOHdo { something; } while (false)
是一种在宏调用后强制使用分号的便捷方法,绝对不允许跟随其他标记。
And another possibility is that there either once was a loop there or iteration is anticipated to be added in the future (e.g. in test-driven development, iteration wasn't needed to pass the tests, but logically it would make sense to loop there if the function needed to be somewhat more general than currently required)
另一种可能性是那里曾经有一个循环,或者预计将来会添加迭代(例如,在测试驱动的开发中,不需要迭代来通过测试,但从逻辑上讲,如果该功能需要比当前所需的更通用)
回答by Hogan
The break as goto is probably the answer, but I will put forward one other idea.
break as goto 可能是答案,但我会提出另一个想法。
Maybe he wanted to have a locally defined variables and used this construct to get a new scope.
也许他想要一个本地定义的变量并使用这个构造来获得一个新的作用域。
Remember while recent C++ allows for {...}
anywhere, this was not always the case.
请记住,虽然最近的 C++ 允许在{...}
任何地方使用,但情况并非总是如此。
回答by Cameron
I've seen it used as a useful pattern when there are many potential exit points for the function, but the same cleanup code is always required regardless of how the function exits.
我已经看到当函数有许多潜在的退出点时,它被用作一种有用的模式,但无论函数如何退出,始终需要相同的清理代码。
It can make a tiresome if/else-if tree a lot easier to read, by just having to break whenever an exit point is reached, with the rest of the logic inline afterwards.
它可以使令人厌烦的 if/else-if 树更容易阅读,只需在到达退出点时中断,然后内联其余逻辑即可。
This pattern is also useful in languages that don't have a goto statement. Perhaps that's where the original programmer learnt the pattern.
这种模式在没有 goto 语句的语言中也很有用。也许这就是最初的程序员学习模式的地方。
回答by Brian Young
I've seen code like that so you can use break
as a goto
of sorts.
我见过这样的代码,所以你可以使用break
某种goto
方式。
回答by John Knoeller
This is just a perversion of while
to get the sematics of goto tidy-up
without using the word goto.
这只是while
在goto tidy-up
不使用 goto 一词的情况下获取语义的一种变态。
It's bad form because when you use otherloops inside the outer while
the breaks
become ambiguous to the reader. "Is this supposed to goto exit? or is this intended only to break out of the inner loop?"
它的坏的形式,因为当你使用其他外内循环while
的breaks
变得模糊给读者。 “这应该是要退出吗?还是只是为了跳出内部循环?”
回答by Robert
I think it's more convenient to write break
instead of goto end
. You don't even have to think up a name for the label which makes the intention clearer: You don't want to jump to a label with a specific name. You want to get out of here.
我觉得用写break
代替goto end
. 您甚至不必为标签想一个名称,这使意图更清晰:您不想跳转到具有特定名称的标签。你想离开这里。
Also chances are you would need the braces anyway. So this is the do{...}while(false);
version:
无论如何,您也有可能需要牙套。所以这是do{...}while(false);
版本:
do {
// code
if (condition) break; // or continue
// more code
} while(false);
And this is the way you would have to express it if you wanted to use goto
:
如果您想使用,这就是您必须表达的方式goto
:
{
// code
if (condition) goto end;
// more code
}
end:
I think the meaning of the first version is much easier to grasp. Also it's easier to write, easier to extend, easier to translate to a language that doesn't support goto
, etc.
我认为第一个版本的含义更容易理解。此外,它更容易编写、更容易扩展、更容易翻译成不支持的语言goto
等。
The most frequently mentioned concern about the use of break
is that it's a badly disguised goto
. But actually break
has more resemblance to return
: Both instructions jump out of a block of code which is pretty much structured in comparison to goto
. Nevertheless both instructions allow multiple exit points in a block of code which can be confusing sometimes. After all I would try to go for the most clear solution, whatever that is in the specific situation.
关于 的使用最常提到的问题break
是它是一个严重伪装的goto
. 但实际上break
更相似的是return
:两条指令都跳出一个代码块,与goto
. 尽管如此,这两条指令都允许在一个代码块中有多个退出点,这有时会令人困惑。毕竟,无论具体情况如何,我都会尝试寻找最清晰的解决方案。
回答by AnT
This trick is used by programmers that are too shy to use an explicit goto
in their code. The author of the above code wanted to have the ability to jump directly to the "cleanup and return" point from the middle of the code. But they didn't want to use a label and explicit goto
. Instead, they can use a break
inside the body of the above "fake" cycle to achieve the same effect.
这个技巧被那些过于害羞而不能goto
在他们的代码中使用显式的程序员使用。上面代码的作者是想拥有从代码中间直接跳转到“清理返回”点的能力。但他们不想使用标签和显式goto
。相反,他们可以使用break
上述“假”循环的内部来达到相同的效果。
回答by Dmitry
It is a very common practice. In C. I try to think of it as if you want to lie to yourselfin a way "I'm not using a goto
". Thinking about it, there would be nothing wrong with a goto
used similarly. In fact it would also reduce indentation level.
这是一种非常普遍的做法。在C 中。我试着把它想象成你想以“我没有使用”的方式对自己撒谎goto
。想想看,goto
类似的用法也没有错。事实上,它也会降低缩进水平。
That said, though, I noticed, very often this do..while
loops tend to grow. And then they get if
s and else
s inside, rendering the code actually not very readable, let alone testable.
尽管如此,我注意到,这个do..while
循环往往会增长。然后他们把if
s 和else
s 放在里面,使代码实际上不是很可读,更不用说可测试了。
Those do..while
are normally intended to do a clean-up. By all means possible I would prefer to use RAIIand return earlyfrom a shortfunction. On the other hand, Cdoesn't provide you as much conveniences as C++does, making a do..while
one of the best approaches to do a cleanup.
这些do..while
通常用于清理。无论如何,我更愿意使用RAII并从一个简短的函数中尽早返回。另一方面,C并没有像C++那样为您提供那么多的便利,这是进行清理的最佳方法之一。do..while
回答by Pete Kirkham
It looks like a C programmer. In C++, automatic variables have destructors which you use to clean up, so there should not be anything needed tidying up before the return. In C, you didn't have this RAIIidiom, so if you have common clean up code, you either goto
it, or use a once-through loop as above.
它看起来像一个 C 程序员。在 C++ 中,自动变量有你用来清理的析构函数,所以在返回之前不应该有任何需要整理的东西。在 C 中,你没有这个RAII习惯用法,所以如果你有通用的清理代码,你要么使用goto
它,要么使用上面的单程循环。
Its main disadvantage compared with the C++ idiom is that it will not tidy up if an exception is thrown in the body. C didn't have exceptions, so this wasn't a problem, but it does make it a bad habit in C++.
与C++习惯用法相比,它的主要缺点是如果在正文中抛出异常,则不会整理。C 没有异常,所以这不是问题,但它确实使它成为 C++ 中的一个坏习惯。