5.7 跳转语句
这些语句可以立即将控制权转移到函数中的其他位置或从函数中返回控制权。
C++ 跳转语句执行控制的即时本地转换。
break;
continue;
return [expression];
goto identifier;
5.7.1 break语句
break 语句可终止执行最近的封闭循环或其所在条件语句。 控制权将传递给该语句结束之后的语句(如果有的话)。
break;
break 语句与 switch 条件语句以及 do、for 和 while 循环语句配合使用。
在 switch 语句中,break 语句将导致程序执行 switch 语句之外的下一语句。如果没有 break语句,则将执行从匹配的case标签到switch语句末尾之间的每个语句,包括 default 子句。
在循环中,break语句将终止执行最近的do、for或while 封闭语句。 控制权将传递给终止语句之后的语句(如果有的话)。
在嵌套语句中,break语句只终止直接包围它的do、for、switch 或 while 语句。 你可以使用 return 或 goto 语句从较深嵌套的结构转移控制权。
以下代码演示如何在 for 循环中使用 break 语句。
#include <iostream>
using namespace std;
int main()
{
// An example of a standard for loop
for (int i = 1; i < 10; i++)
{
cout << i << '\n';
if (i == 4)
break;
}
// An example of a range-based for loop
int nums []{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i : nums) {
if (i == 4) {
break;
}
cout << i << '\n';
}
}
以下代码演示如何在 while 循环和 do 循环中使用 break。
#include <iostream>
using namespace std;
int main() {
int i = 0;
while (i < 10) {
if (i == 4) {
break;
}
cout << i << '\n';
i++;
}
i = 0;
do {
if (i == 4) {
break;
}
cout << i << '\n';
i++;
} while (i < 10);
}
以下代码演示如何在 switch 语句中使用 break。 如果你要分别处理每个用例,则必须在每个用例中使用 break;如果不使用 break,则执行下一用例中的代码。
#include <iostream>
using namespace std;
enum Suit{ Diamonds, Hearts, Clubs, Spades };
int main() {
Suit hand;
. . .
// Assume that some enum value is set for hand
// In this example, each case is handled separately
switch (hand)
{
case Diamonds:
cout << "got Diamonds \n";
break;
case Hearts:
cout << "got Hearts \n";
break;
case Clubs:
cout << "got Clubs \n";
break;
case Spades:
cout << "got Spades \n";
break;
default:
cout << "didn't get card \n";
}
// In this example, Diamonds and Hearts are handled one way, and
// Clubs, Spades, and the default value are handled another way
switch (hand)
{
case Diamonds:
case Hearts:
cout << "got a red card \n";
break;
case Clubs:
case Spades:
default:
cout << "didn't get a red card \n";
}
}
5.7.2 continue语句
强制转移对最小封闭 do、for 或 while 循环的控制表达式的控制。
continue;
将不会执行当前迭代中的所有剩余语句。 确定循环的下一次迭代,如下所示:
1)在 do 或 while 循环中,下一个迭代首先会重新计算 do 或 while 语句的控制表达式。
2)在 for 循环中(使用语法 for(init-expr; cond-expr; loop-expr)),将执行 loop-expr 子句。 然后,重新计算 cond-expr 子句,并根据结果确定该循环结束还是进行另一个迭代。
下面的示例演示了如何使用 continue 语句跳过代码部分并启动循环的下一个迭代。
// continue_statement.cpp
#include <>
int main()
{
int i = 0;
do
{
i++;
printf_s("before the continue\n");
continue;
printf("after the continue, should never print\n");
} while (i < 3);
printf_s("after the do loop\n");
}
5.7.3 return语句
终止函数的执行并返回对调用函数的控制(或对操作系统的控制,如果您从 main 函数转移控制)。 紧接在调用之后在调用函数中恢复执行。
return [expression];
expression 子句(如果存在)将转换为函数声明中指定的类型,就像正在执行初始化一样。 从该类型的表达式到 return 类型的函数的转换会创建临时对象。
expression 子句的值将返回调用函数。如果省略该表达式,则函数的返回值是不确定的。 构造函数和析构函数以及类型为 void 的函数无法在 return 语句中指定表达式。 所有其他类型的函数必须在return语句中指定表达式。
当控制流退出封闭函数定义的块时,结果将与执行不带表达式return语句所获得的结果一样。这对于声明为返回值的函数无效。
一个函数可以包含任意数量的 return 语句。
以下示例将一个表达式与 return 语句一起使用来获取两个整数中的最大者。
// return_statement2.cpp
#include <>
int max ( int a, int b )
{
return ( a > b ? a : b );
}
int main()
{
int nOne = 5;
int nTwo = 7;
printf_s("\n%d is bigger\n", max( nOne, nTwo ));
}
5.7.4 goto语句
goto 语句无条件传输控件到由指定的标识符标记的语句。
goto identifier;
identifier 指定的该标记语句必须位于当前函数。 所有identifier名称是内部命名空间的成员,因此它们不影响其他标识符。
语句标签仅对 goto 语句有意义;否则,语句标签被忽略。 标签不能重新声明。
goto 不允许语句将控制转移到跳过初始化该位置范围内的任何变量的位置。 下面的示例引发 C2362:
int goto_fn(bool b)
{
if (!b)
{
goto exit; // C2362
}
else
{ /*...*/ }
int error_code = 42;
exit:
return error_code;
}
尽可能使用 break、continue 和 return 语句来代替 goto 语句是好的编程样式。 但是,因为 break 语句仅从循环的一个级别退出,可能必须使用 goto 语句退出一个深层嵌套循环。
在此示例中, goto 语句将控制权转交给标记为 stop i 等于3的点。
// goto_statement.cpp
#include <>
int main()
{
int i, j;
for ( i = 0; i < 10; i++ )
{
printf_s( "Outer loop executing. i = %d\n", i );
for ( j = 0; j < 2; j++ )
{
printf_s( " Inner loop executing. j = %d\n", j );
if ( i == 3 )
goto stop;
}
}
// This message does not print:
printf_s( "Loop exited. i = %d\n", i );
stop:
printf_s( "Jumped to stop. i = %d\n", i );
}
5.7.5 控制的转移
您可以 goto、case 在语句中使用语句或标签 switch 来指定分支过时的程序。 此类代码是非法的,除非包含初始值设定项的声明在跳转语句发生的块所封闭的块中。
下面的示例显示了声明和初始化对象 total、ch 和 i 的循环。 还有一个错误的 goto 语句,它将控制转移到初始值设定项之后。
// transfers_of_control.cpp
// compile with: /W1
// Read input until a nonnumeric character is entered.
int main()
{
char MyArray[5] = {'2','2','a','c'};
int i = 0;
while( 1 )
{
int total = 0;
char ch = MyArray[i++];
if ( ch >= '0' && ch <= '9' )
{
goto Label1;
int i = ch - '0';
Label1:
total += i; // C4700: transfers past initialization of i.
} // i would be destroyed here if goto error were not present
else
// Break statement transfers control out of loop,
// destroying total and ch.
break;
}
}
在前面的示例中 goto 语句尝试将控制转移到的初始化之后 i 。但是,如果已声明但未初始化 i,则该传递是合法的。
total、ch、while 当使用语句退出该块时,将销毁在块中声明的对象和(用作语句的语句) break 。