8-11 break和continue
中断(break)
虽然你已经在switch语句的上下文中见过break语句break statement (8.5节——switch语句基础),但它值得更全面的探讨,因为它也可用于其他类型的控制流语句。break语句会导致while循环、do-while循环、for循环或switch语句终止,执行流程将跳转至跳出循环或switch语句后的下一条语句。
中断 switch
在switch语句中,break语句通常用于每个case语句的末尾,以表示该case已结束(从而防止执行流程落入后续的case语句):
#include <iostream>
void printMath(int x, int y, char ch)
{
switch (ch)
{
case '+':
std::cout << x << " + " << y << " = " << x + y << '\n';
break; // don't fall-through to next case
case '-':
std::cout << x << " - " << y << " = " << x - y << '\n';
break; // don't fall-through to next case
case '*':
std::cout << x << " * " << y << " = " << x * y << '\n';
break; // don't fall-through to next case
case '/':
std::cout << x << " / " << y << " = " << x / y << '\n';
break;
}
}
int main()
{
printMath(2, 3, '+');
return 0;
}
参见第8.6节——switch语句的贯穿与作用域,以获取更多关于贯穿的信息及更多示例。
中断循环
在循环语句中,break语句可用于提前终止循环。执行将跳至循环结束后的下一条语句继续进行。
例如:
#include <iostream>
int main()
{
int sum{ 0 };
// Allow the user to enter up to 10 numbers
for (int count{ 0 }; count < 10; ++count)
{
std::cout << "Enter a number to add, or 0 to exit: ";
int num{};
std::cin >> num;
// exit loop if user enters 0
if (num == 0)
break; // exit the loop now
// otherwise add number to our sum
sum += num;
}
// execution will continue here after the break
std::cout << "The sum of all the numbers you entered is: " << sum << '\n';
return 0;
}
该程序允许用户输入最多10个数字,并在最后显示所有输入数字的总和。若用户输入0,则循环将提前终止(即在输入10个数字之前)。
以下是上述程序的运行示例:

中断也是摆脱故意设置的无限循环的常用方法:
#include <iostream>
int main()
{
while (true) // infinite loop
{
std::cout << "Enter 0 to exit or any other integer to continue: ";
int num{};
std::cin >> num;
// exit loop if user enters 0
if (num == 0)
break;
}
std::cout << "We're out!\n";
return 0;
}
上述程序的示例运行:

break 与 return 的区别
新手程序员有时难以理解 break 和 return 的区别。break 语句会终止 switch 或循环结构,执行流程将跳转至该结构之后的第一条语句。而 return 语句会终止包含该循环的整个函数,执行流程将返回至函数被调用的位置。
#include <iostream>
int breakOrReturn()
{
while (true) // infinite loop
{
std::cout << "Enter 'b' to break or 'r' to return: ";
char ch{};
std::cin >> ch;
if (ch == 'b')
break; // execution will continue at the first statement beyond the loop
if (ch == 'r')
return 1; // return will cause the function to immediately return to the caller (in this case, main())
}
// breaking the loop causes execution to resume here
std::cout << "We broke out of the loop\n";
return 0;
}
int main()
{
int returnValue{ breakOrReturn() };
std::cout << "Function breakOrReturn returned " << returnValue << '\n';
return 0;
}
以下是该程序的两次运行结果:


继续
continue语句continue statement提供了一种便捷的方式,可在不终止整个循环的情况下结束当前循环迭代。
以下是使用 continue 的示例:
#include <iostream>
int main()
{
for (int count{ 0 }; count < 10; ++count)
{
// if the number is divisible by 4, skip this iteration
if ((count % 4) == 0)
continue; // go to next iteration
// If the number is not divisible by 4, keep going
std::cout << count << '\n';
// The continue statement jumps to here
}
return 0;
}
该程序打印所有不能被4整除的0到9之间的数字:

continue语句的作用是使当前执行点跳转到当前循环的末尾。
在for循环中,即使执行了continue语句,for循环的结束语句(如上例中的++count)仍会执行(因为该操作发生在循环体结束之后)。
在while或do-while循环中使用continue语句时需格外谨慎。这类循环通常会改变循环体内部条件语句所使用的变量值。若continue语句导致这些语句被跳过,则可能引发无限循环!
请考虑以下程序:
#include <iostream>
int main()
{
int count{ 0 };
while (count < 10)
{
if (count == 5)
continue; // jump to end of loop body
std::cout << count << '\n';
++count; // this statement is never executed after count reaches 5
// The continue statement jumps to here
}
return 0;
}
该程序旨在打印0到9之间的所有数字,但不包括5。然而它实际输出了:

然后进入无限循环。当计数为5时,if语句评估为真,而continue语句导致执行跳转到循环底部。计数变量永远不会递增。因此,在下一次迭代中,计数仍为5,if语句依然为真,程序将持续无限循环。
当然,你应该已经知道:当存在明确的计数变量时,应当使用 for 循环而非 while 或 do while 循环。
关于break和continue语句使用的争论
许多教材告诫读者不要在循环中使用break和continue语句,一方面是因为它们会导致执行流程跳跃,另一方面则会使逻辑流程更难理解。例如,在复杂逻辑的中间位置插入break语句,可能会被忽略,或者难以明确其触发条件。
然而,若审慎使用,break和continue能通过减少嵌套代码块数量、降低复杂循环逻辑需求,从而提升循环可读性。
例如,请看以下程序:
#include <iostream>
int main()
{
int count{ 0 }; // count how many times the loop iterates
bool keepLooping { true }; // controls whether the loop ends or not
while (keepLooping)
{
std::cout << "Enter 'e' to exit this loop or any other character to continue: ";
char ch{};
std::cin >> ch;
if (ch == 'e')
keepLooping = false;
else
{
++count;
std::cout << "We've iterated " << count << " times\n";
}
}
return 0;
}
该程序使用布尔变量控制循环是否继续,并包含一个嵌套代码块——该代码块仅在用户未退出时执行。
以下是使用break语句实现的更易理解的版本:
#include <iostream>
int main()
{
int count{ 0 }; // count how many times the loop iterates
while (true) // loop until user terminates
{
std::cout << "Enter 'e' to exit this loop or any other character to continue: ";
char ch{};
std::cin >> ch;
if (ch == 'e')
break;
++count;
std::cout << "We've iterated " << count << " times\n";
}
return 0;
}
在此版本中,通过使用单个break语句,我们避免了布尔变量的使用(及其用途和取值位置的理解需求)、else语句以及嵌套代码块。
continue语句最有效地应用于for循环顶部,用于在满足某些条件时跳过循环迭代。这使我们能够避免使用嵌套代码块。
例如,与以下代码相比:
#include <iostream>
int main()
{
for (int count{ 0 }; count < 10; ++count)
{
// if the number is not divisible by 4...
if ((count % 4) != 0) // nested block
{
// Print the number
std::cout << count << '\n';
}
}
return 0;
}
我们可以这样写:
#include <iostream>
int main()
{
for (int count{ 0 }; count < 10; ++count)
{
// if the number is divisible by 4, skip this iteration
if ((count % 4) == 0)
continue;
// no nested block needed
std::cout << count << '\n';
}
return 0;
}
减少使用的变量数量和降低嵌套代码块的层级,对提升代码可读性的效果远大于使用break或continue语句造成的损害。因此,我们认为审慎使用break或continue是可接受的。
最佳实践
当break和continue语句能简化循环逻辑时,请使用它们。
关于提前返回的争论
关于return语句同样存在类似的争论。若return语句并非函数中的最后一条语句,则称为提前返回。许多程序员认为应避免使用提前返回early return。仅在函数末尾包含一条return语句的函数具有简洁性——你可以假设该函数会接收实参,执行其实现的逻辑,并直接返回结果而不偏离流程。额外的返回语句会使逻辑复杂化。
反驳观点认为:使用提前返回能让函数在完成任务后立即退出,既减少了阅读冗余逻辑的负担,又最大限度降低了条件嵌套代码块的需求,从而提升代码可读性。
部分开发者采取折中方案:仅在函数开头使用提前返回进行形参验证(捕获无效实参),之后仅保留单个返回语句。
我们的立场是:提前返回利大于弊,但承认这种实践需要一定技巧。

浙公网安备 33010602011771号