当我还是大一的时候,我们的教练允许我们使用break
或continue
循环。那时我大部分时间都这样做,因为它终止/继续循环。现在我大二了,我的导师告诉我不建议使用break
/ 。continue
你能告诉我为什么吗?顺便说一句,什么会影响中断/继续?
3 回答
有些人认为控制流过于复杂是不好的,这意味着像break
,continue
和多个return
s 之类的东西。原因不是技术性的,主要是复杂的控制流会使程序的验证、测试和推理变得更加困难。
然而,这在很大程度上取决于风格、个人品味和您的整体结构。使用小型、用途良好的功能,拥有多个可能的流程可能几乎没有害处。特别是在 C++ 中,提前退出是一种流行的习惯用法,通常可以使代码更容易理解。
至少在 C 中,您不应该使用break
和/或continue
“大部分时间”(正如您的问题所说的那样)来控制循环的流程。您的循环条件应指示循环应在什么情况下停止;维护您的代码的人不必深入研究循环主体中的代码,以查看break
导致循环停止的触发因素。
例如,假设您想从文件中读取多个整数,inputFile
以查看其中一个整数是否为 500。构造循环的一种方法是:
while (fgets (buffer, sizeof (buffer), inputFile)){
sscanf (buffer, "%d", &num);
if (num == 500)
break;
}
在这里,阅读您的代码的人必须阅读您的整个while
循环,以找出您在文件中实际查找的内容。如果你写这个没有break
:
while ((num != 500) && fgets (buffer, sizeof (buffer), inputFile))
sscanf (buffer, "%d", &num);
循环条件本身可以准确地告诉读者您的代码要做什么,这使得它更容易快速理解。此外,作为奖励,您节省了几行代码。
现在想象一个更复杂的while
或for
循环,其中break
深埋在循环体内。很容易看出为什么试图找到break
触发器会变得烦人。拥有一个结构合理的循环条件更多,嗯,自我记录。
当然,在某些情况下break
,continue
实际上是编写代码的好方法。例如,如果循环应该结束的条件可能发生在循环执行的中间,并且循环内部有很长的语句集,并且执行这些语句会增加处理时间而没有完成任何有用的事情,当然,继续使用break
. 但这些情况是例外,而不是“大多数时候”。
我见过的大多数关于代码正确性的推理逻辑都假设单入口/单出口。如果你的循环用break
and填充continue
,就不可能知道你的循环不变量是否得到满足,或者你是否总是取得进展(所以循环不会是无止境的)。(请注意,do
{ ... } while (...);
循环也受此影响;循环不变量不是第一次建立的,这可能会导致一些意外。)
在您想使用break
or
的大多数情况下continue
,您可能使循环(以及包含它的函数)太大且太复杂。
有些人会争辩说:
for (;;) {
// ...
if ( conditionMet ) {
break;
}
// ...
}
对于经典循环和半成语来说是可以接受的;毕竟,它是单入口/单出口,即使出口不是我们所期望的(并且在阅读代码时很难找到)。关于循环不变量的问题仍然存在;之前没有遇到过if
,至少是第一次遇到。通常,更好的解决方案是将测试之前的代码放入一个单独的函数中,该函数返回conditionMet
,并使用:
while ( doLoopPrefix() ) {
doLoopSuffix();
}
(一般来说,如果你的循环超过三四行,你应该重构。除非它包含一个switch
语句,而且有很多情况。)