在for循环中使用break是不好的做法?

for循环中使用break语句是不好的做法?

说,我正在一个数组中寻找一个值。 在for循环中进行比较,当find值时, break; 退出for循环。

这是不好的做法? 我已经看到了使用的替代方法:定义一个variablesvFound并find值时设置为true,并在for语句条件检查vFound 。 但是为了这个目的,是否需要创build一个新的variables?

我正在问一个正常的C或C ++循环的上下文。

PS: MISRA编码准则build议不要使用中断。

这里有很多答案,但我还没有看到这个提到:

如果您编写整洁易读的循环,大多数与在for循环中使用breakcontinue相关的“危险”都将被否定。 如果你的循环的主体跨越了几个屏幕的长度,并有多个嵌套的子块,是的,你可以很容易忘记一些代码将不会执行rest后。 但是,如果这个循环是短暂的,那么断言的目的应该是显而易见的。

如果循环变得太大,请在循环中使用一个或多个有名的函数调用。 避免这样做的唯一真正原因是处理瓶颈。

不,rest是正确的解决scheme。

添加布尔variables会使代码更难读取,并增加潜在的错误来源。

你可以find各种各样的专业代码与他们的'打破'的声明。 在必要时使用它是完全有意义的。 在你的情况下,这个选项比创build一个单独的variables更好,只是出于循环的目的。

使用break以及在for循环中continue是非常好的。

它简化了代码并提高了可读性。

Python(和其他语言)远不是坏习惯,扩展了for循环结构,所以只有在循环没有 break 才会执行它的一部分。

 for n in range(5): for m in range(3): if m >= n: print 'stop!' break print m, else: print 'finished.' 

输出:

 stop! 0 stop! 0 1 stop! 0 1 2 finished. 0 1 2 finished. 

等价的代码没有break和那个方便的else

 for n in range(5): aborted = False for m in range(3): if not aborted: if m >= n: print 'stop!' aborted = True else: print m, if not aborted: print 'finished.' 

这取决于语言。 虽然你可以在这里检查一个布尔variables:

 for (int i = 0; i < 100 && stayInLoop; i++) { ... } 

在数组上运行时不可能这样做:

 for element in bigList: ... 

无论如何, break会使两个代码更具可读性。

一般规则:如果遵守规则要求你做一些比较笨拙和难以阅读的事情,那就违反规则,然后打破规则。

在循环的情况下,直到你find了一些东西,你会遇到区分find问题,而不是当你离开时找不到。 那是:

 for (int x=0;x<fooCount;++x) { Foo foo=getFooSomehow(x); if (foo.bar==42) break; } // So when we get here, did we find one, or did we fall out the bottom? 

所以没关系,你可以设置一个标志,或者初始化一个“find”值为null。 但

这就是为什么一般来说,我更喜欢把我的search推到function上:

 Foo findFoo(int wantBar) { for (int x=0;x<fooCount;++x) { Foo foo=getFooSomehow(x); if (foo.bar==wantBar) return foo; } // Not found return null; } 

这也有助于清理代码。 在主线上,“查找”成为一个单一的陈述,当条件复杂时,它们只写一次。

使用break语句没有任何内在的错误,但嵌套循环可能会让人困惑。 为了提高可读性,许多语言( 至lessJava )支持打破标签,这将大大提高可读性。

 int[] iArray = new int[]{0,1,2,3,4,5,6,7,8,9}; int[] jArray = new int[]{0,1,2,3,4,5,6,7,8,9}; // label for i loop iLoop: for (int i = 0; i < iArray.length; i++) { // label for j loop jLoop: for (int j = 0; j < jArray.length; j++) { if(iArray[i] < jArray[j]){ // break i and j loops break iLoop; } else if (iArray[i] > jArray[j]){ // breaks only j loop break jLoop; } else { // unclear which loop is ending // (breaks only the j loop) break; } } } 

我会说break(和return)语句经常会增加圈复杂度 ,这使得certificate代码在所有情况下都做正确的事情变得更加困难。

如果您正在考虑在迭代某个特定项目的序列时使用中断,则可能需要重新考虑用于保存数据的数据结构。 使用类似Set或Map的东西可能会提供更好的结果。

打破是一个完全可以接受的语句使用(所以是继续 ,顺便说一句)。 这完全是关于代码可读性的 – 只要你没有太复杂的循环,就没有问题。

这不像他们是一样的联赛。 🙂

在你的例子中,你不知道for循环的迭代次数。 为什么不使用while循环,这使迭代次数在开始时是不确定的?

因此,通常不需要使用break语句 ,因为循环可以更好地表示为while循环。

我同意推荐使用break其他人。 明显的结果性问题是为什么有人会推荐呢? 那么…当你使用break时,你跳过块中剩下的代码,剩下的迭代。 有时这会导致错误,例如:

  • 在块顶部获得的资源可能会在底部被释放(即使对于循环内部的块也是如此),但是当由于断言而导致“过早”退出时,该释放步骤可能被意外跳过(在“现代的“C ++”,“RAII”用于以可靠和exception安全的方式处理这个问题:基本上,对象析构函数可靠地释放资源,而不pipe范围如何退出)

  • 有人可能会更改for语句中的条件testing,而不会注意到还有其他离开的退出条件

  • ndim的回答指出,有些人可能会避免break来维持一个相对一致的循环运行时间,但是你要比较break和使用布尔型早退出控制variables的情况,

有时候,观察这些错误的人意识到,通过这个“不间断”的规则可以防止/减轻这个错误……实际上,对于“安全的”编程有一个相关的策略,叫做“结构化编程”,每个函数都应该有一个单一的进出口点(即没有转到,不提前回报)。 它可能会消除一些错误,但无疑会引入其他错误。 他们为什么这样做?

  • 他们有一个鼓励特定风格的编程/代码的开发框架,而且他们有统计证据表明这在这个有限的框架中产生了净效益,或者
  • 他们已经受到这样的框架内的编程指导或经验的影响,或者
  • 他们只是独裁的白痴,或者
  • 上述任何一种+历史惯性(因为理由比现代C ++更适用于C)。

正如其他人指出的那样,使用break是完全有效的,它与goto联赛没有任何关系。

虽然当您想要在循环外部检查在数组中是否find该值时,您可能需要使用vFoundvariables。 同样从可维护性的angular度来看,具有通用标志表示退出标准可能是有用的。

我没有看到任何理由,这是一个不好的做法提供,你要完成停止处理在这一点上。

在embedded式世界中,有很多代码使用以下结构:

  while(1) { if (RCIF) gx(); if (command_received == command_we_are_waiting_on) break; else if ((num_attempts > MAX_ATTEMPTS) || (TickGet() - BaseTick > MAX_TIMEOUT)) return ERROR; num_attempts++; } if (call_some_bool_returning_function()) return TRUE; else return FALSE; 

这是一个非常普遍的例子,幕后发生了很多事情,尤其是中断。 不要使用这个作为样板代码,我只是想说明一个例子。

我个人的观点是,只要采取适当的措施防止无限期地留在循环中,以这种方式编写一个循环就没有问题。

取决于你的用例。 有些应用程序的for循环的运行时间需要保持不变(例如,为了满足一些时序约束,或者将数据内部隐藏到基于时序的攻击)。

在这些情况下,甚至可以设置一个标志,只有在所有for循环迭代实际运行后才检查标志值。 当然,所有for循环迭代都需要运行相同时间的代码。

如果你不在乎运行时间…使用break;continue; 使代码更易于阅读。

关于MISRA 98规则,这是在我的公司在C开发中使用,break语句不应该被使用…

编辑:中断在MISRA '04允许

当然, break; 是停止for循环或foreach循环的解决scheme。 我用它在PHP中的foreach和循环,发现工作。

我不同意!

为什么你会忽略for循环的内置function来创build自己的? 你不需要重新发明轮子。

我认为在你的for循环的顶部有这样的检查是更有意义的

 for(int i = 0; i < myCollection.Length && myCollection[i].SomeValue != "Break Condition"; i++) { //loop body } 

或者如果您需要先处理该行

 for(int i = 0; i < myCollection.Length && (i == 0 ? true : myCollection[i-1].SomeValue != "Break Condition"); i++) { //loop body } 

这样你就可以编写一个函数来执行所有的事情,并且制作更清晰的代码。

 for(int i = 0; i < myCollection.Length && (i == 0 ? true : myCollection[i-1].SomeValue != "Break Condition"); i++) { DoAllThatCrazyStuff(myCollection[i]); } 

或者如果你的情况很复杂,你也可以把这个代码移出来!

 for(int i = 0; i < myCollection.Length && BreakFunctionCheck(i, myCollection); i++) { DoAllThatCrazyStuff(myCollection[i]); } 

充满rest的“专业代码”对我来说听起来并不像专业代码。 这听起来像是懒惰的编码;)

我对我目前正在使用的代码库(40,000行JavaScript)做了一些分析。

我发现只有22个break其中:

  • switch语句中使用了19个(我们总共只有3个switch语句)。
  • 2 for循环内部 – 我立即将其分类为要重构为单独的函数并用return语句replace的代码。
  • 至于循环里面的最后一个break …我跑了git blame看看谁写这个废话!

所以根据我的统计: 如果在switch外使用break ,这是一种代码异味。

我也search了continue发言。 没有发现。