在循环中使用break语句是不好的做法?for
说,我在数组中搜索一个值.比较for循环内部和找到值时,break;退出for循环.
这是一种不好的做法吗?我已经看到了使用替代:定义一个变量vFound,当被发现的价值它设置为true,并检查vFound在for语句条件.但是,是否有必要为此目的创建一个新变量?
我在正常的C或C++ for循环的上下文中询问.
PS:MISRA编码指南建议不要使用break.
smi*_*man 132
不,休息是正确的解决方案.
添加布尔变量会使代码更难读取并添加潜在的错误源.
e.J*_*mes 112
这里有很多答案,但我还没有看到这个提到:
如果你编写整洁,易读的循环,那么与使用break或continuefor循环相关的大多数"危险"都会被否定.如果循环的主体跨越多个屏幕长度并且具有多个嵌套子块,是的,您可能很容易忘记在中断后不会执行某些代码.但是,如果循环很短且非常重要,则break语句的目的应该是显而易见的.
如果循环变得太大,请在循环中使用一个或多个命名良好的函数调用.避免这样做的唯一真正原因是处理瓶颈.
Nic*_*k T 21
Python(以及其他语言?)远非不好的做法,它扩展了for循环结构,因此只有循环不 执行才能执行部分循环结构break.
for n in range(5):
for m in range(3):
if m >= n:
print('stop!')
break
print(m, end=' ')
else:
print('finished.')
Run Code Online (Sandbox Code Playgroud)
输出:
stop!
0 stop!
0 1 stop!
0 1 2 finished.
0 1 2 finished.
Run Code Online (Sandbox Code Playgroud)
没有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, end=' ')
if not aborted:
print('finished.')
Run Code Online (Sandbox Code Playgroud)
Jay*_*Jay 14
一般规则:如果遵循规则要求您做一些更尴尬和难以阅读的事情然后违反规则,那么打破规则.
在循环直到你找到某些东西的情况下,你会遇到区分发现与未找到的问题.那是:
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?
Run Code Online (Sandbox Code Playgroud)
好的,你可以设置一个标志,或者将"found"值初始化为null.但
这就是为什么我更喜欢将我的搜索推送到函数中:
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;
}
Run Code Online (Sandbox Code Playgroud)
这也有助于整理代码.在主线中,"find"成为单个语句,当条件复杂时,它们只写一次.
cyb*_*onk 14
使用break语句没有任何内在错误,但嵌套循环可能会让人感到困惑.为了提高可读性,许多语言(至少Java确实如此)支持打破标签,这将极大地提高可读性.
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我会说断开(和返回)语句通常会增加圈复杂度,这使得在所有情况下证明代码执行正确的事情变得更加困难.
如果您正在考虑在迭代某个特定项目的序列时使用中断,则可能需要重新考虑用于保存数据的数据结构.使用Set或Map之类的东西可以提供更好的结果.
eum*_*iro 13
这取决于语言.虽然你可以在这里检查一个布尔变量:
for (int i = 0; i < 100 && stayInLoop; i++) { ... }
Run Code Online (Sandbox Code Playgroud)
在数组上进行itering时无法执行此操作:
for element in bigList: ...
Run Code Online (Sandbox Code Playgroud)
无论如何,break会使两个代码更具可读性.
riv*_*era 13
break是一个完全可以接受的语句(所以继续,顺便说一句).这都是关于代码可读性的 - 只要你没有过于复杂的循环等等,它就没问题了.
这并不像他们和goto一样.:)
在您的示例中,您不知道for循环的迭代次数.为什么不使用while循环,这允许迭代次数在开始时是不确定的?
因此,通常不必使用中断状态,因为循环可以更好地表示为while循环.
我同意推荐使用的其他人break.显而易见的重要问题是为什么有人会这样推荐?好吧......当你使用break时,你跳过块中的其余代码,以及剩余的迭代.有时这会导致错误,例如:
在块顶部获取的资源可以在底部释放(即使对于for循环内的块也是如此),但是当break语句(在"现代"中)导致"过早"退出时,可能会意外跳过该释放步骤C++,"RAII"用于以可靠和异常安全的方式处理这个问题:基本上,无论退出范围如何,对象析构函数都可以可靠地释放资源)
有人可能会在for声明中更改条件测试而不会注意到其他非本地化的退出条件
ndim的回答观察到有些人可能会避免使用breaks来保持相对一致的循环运行时间,但是你要比较break使用布尔值早期退出控制变量而不是
观察这些错误的人偶尔会意识到可以通过这种"无中断"规则来防止/减轻这种错误......事实上,有一个完整的"安全"编程策略称为"结构化编程",其中每个函数应该具有单个入口和出口点(即没有转到,没有提前返回).它可能会消除一些错误,但无疑会引入其他错误.他们为什么这样做?
小智 5
使用完全有效break- 正如其他人所指出的那样,它在同一个联盟中无处可去goto.
虽然您可能希望vFound在循环外部检查是否在数组中找到该值时使用该变量.同样从可维护性的观点来看,具有用信号通知退出标准的公共标志可能是有用的.
在嵌入式世界中,有很多代码使用以下结构:
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;
Run Code Online (Sandbox Code Playgroud)
这是一个非常普遍的例子,很多事情都在幕后发生,特别是中断。不要将此用作样板代码,我只是想说明一个示例。
我个人的观点是,只要采取适当的措施防止无限期地保留在循环中,以这种方式编写循环并没有什么问题。
我对当前正在使用的代码库(40,000行JavaScript)进行了一些分析。
我发现其中只有22条break陈述:
switch语句使用了19个(总共只有3个switch语句!)。for循环内部使用了2个-我立即将其分类为代码,将其重构为单独的函数并替换为return语句。break内部while循环……我跑去git blame看看谁写了这个废话!所以根据我的统计:如果break在之外使用switch,则是代码异味。
我还搜索continue语句。一无所获。