我该如何从循环中跳出来
How should I break out from a loop?
每当我需要从C++中的for(unsigned int i=0;i<bound;++i)
表达式中突破时,我只需设置索引变量i=bound
,方法与本答案中描述的相同。我倾向于避免使用break
语句,因为老实说,我不太了解它的实际作用。
比较两条指令:
for(unsigned int i=0;i<bound;++i) {
if (I need a break) {
break;
}
}
和
for(unsigned int i=0;i<bound;++i) {
if (I need a break) {
i=bound;
}
}
我推测,第二种方法在i
和bound
之间做了一个额外的变量集,然后进行了一次额外的比较,因此从性能的角度来看,它看起来更加昂贵。那么问题是,调用break
,然后进行这两个测试是否更便宜?编译后的二进制文件有什么不同吗?有没有第二种方法失败的例子,或者我可以安全地选择这两种方法中的任何一种?
Related:"break"是否仅适用于"for"、"while"、"do while"answers"switch';以及"if"语句?
在没有break语句的情况下中断循环[C]
使用break将更经得起未来的考验,也更符合逻辑。
考虑以下示例,
for (i = 0; i < NUM_OF_ELEMENTS; i++)
{
if(data[i] == expected_item)
break;
}
printf("n Element %d is at index %dn", expected_item, i);
但第二种方法在这里没有用处。
- 正如其他人所说,如果您的索引变量不局限于
for
作用域,break
会保持其不变,而您的方法会破坏其内容;当你搜索一个带有break
的数组时,代码会更简洁(你不必保留一个额外的变量来写下你停止的地方) CCD_ 10立即退出循环;您的方法要求您执行正文的其余部分。当然,你总是可以写:
for(int i=0; i<n; ++i) { if(...) { i=n; } else { rest of the loop body } }
但它给你的循环增加了视觉和逻辑上的混乱;
break
几乎肯定会被转换为简单的jmp
,转换为循环后的指令(尽管,如果你有带析构函数的块范围变量,情况可能会更复杂);编译器不一定会将您的解决方案识别为等效解决方案。实际上,您可以在这里看到,gcc一直生成将
n
移动到i
的代码,而在第二种情况下,它直接跳出循环。
在风格方面:
- 我发现"你的方式"过于复杂且不地道——如果我在真实代码中遇到它,我会问自己"他为什么不使用
break
?" - 正如其他人所说,你的内部任务有与实际循环条件不同步的风险
- 当循环条件变得比简单的范围检查更复杂时,无论是在逻辑方面(如果循环条件很复杂,那么欺骗它可能会变得更复杂)还是在性能方面(如果环路条件很昂贵,并且你已经知道你想退出,你不想再检查它),它都不会缩放;这也可以通过添加一个额外的变量来避免(通常在缺乏
break
的语言中这样做),但这又是对算法实际工作的额外干扰 - 它根本不适用于基于范围的循环
我更喜欢break;
,因为它保持循环变量不变
我经常在搜索时使用这个表格:
int i;
for(i=0; i<list.size(); ++i)
{
if (list[i] == target) // I found what I'm looking for!
{
break; // Stop searching by ending the loop.
}
}
if (i == list.size() ) // I still haven't found what I'm looking for -U2
{
// Not found.
}
else
{
// Do work with list[i].
}
编译后的二进制文件不同吗
几乎可以肯定是的
(尽管优化器可能会识别您的模式,并将其简化为几乎相同)break;
语句可能是一个程序集"跳转"语句,用于跳转到列表外的下一条指令,同时保持控制变量不变。
分配变量(在未优化的代码中)将导致对控制变量的分配、对该变量的测试,然后产生结束循环的跳转。
正如其他人所提到的,如果循环条件在未来发生变化,那么将变量指定为其最终值就不那么经得起未来的考验。
一般来说,当您说:
"我不太了解它的实际作用。(所以我使用了一个变通方法)",
我回复:
"花点时间学习它的作用!作为程序员,你工作的一个主要方面是学习东西。"
使用break
来做这件事是惯用的,应该是默认的,除非出于某种原因,相当模糊的替代方案为下面的逻辑设置了舞台。即便如此,我还是倾向于在循环退出后进行变量设置,为了清晰起见,将该设置移到更接近其用法的位置。
我无法想象这样一种情况:性能足够重要,以至于需要担心。也许一个更复杂的例子可以证明这一点。如前所述,这个问题的答案几乎总是"先量后调"。
除了break
语句退出for
或[do
]while
循环外,还允许使用goto
来中断嵌套循环,例如:
for (i=0; i<k; i++) {
for (j=0; j<l; j++) {
if (someCondition) {
goto end_i;
}
}
}
end_i:
- 如何循环打印顶点结构
- 如何在C++中从两个单独的for循环中添加两个数组
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 正在尝试了解输入验证循环
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 循环后如何继续阅读
- Ardunio UNO解决了多个重叠的定时器循环
- Eigen如何在容器循环中干净地附加矩阵
- 在某些循环内使用vector.push_back时出现分段错误
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 为什么我的for循环不能正确获取argv
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- while循环中while循环的时间复杂度是多少
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 为什么在这个代码结束循环中没有得到结束
- 在基于范围的for循环中使用结构化绑定声明
- 用于C++中带有数组和指针的循环
- 循环中的随机函数
- 是什么阻止DOMTimerCoordinator::NextID进入无休止的循环
- 在循环C++中指定字符串之后,不会打印该字符串