无条件转移控制流。
当使用其他语句不可能将控制转移到所需位置时使用。
语法
属性(可选) goto 标号 ; | ||
解释
goto 语句将控制转移到标号所指定的位置。goto 语句必须与它所用的 标号 处于相同的函数中,它出现于标号的前后均可。
若控制的转移退出了任何自动变量的作用域(例如通过回跳到这种变量声明之前的位置,或向前跳出作为变量作用域的复合语句),则为所有退出作用域的变量以其构造顺序的逆序调用析构函数。
goto
不能将控制转移到 try 块或 catch 子句之内,但能将控制转移离开 try 块或 catch 子句(遵循上述有关作用域中的自动变量的规则)
若控制被转移进入了任何自动变量的作用域(例如通过向前跳过声明语句),则程序非良构(不能编译),除非进入作用域的所有变量拥有
1) 标量类型,且声明不带初始化器
2) 拥有平凡默认构造函数和析构函数的类类型,且声明不带初始化器
3) 上述之一的 cv 限定版本
4) 上述之一的数组
(注意:相同规则适用于控制转移的所有形式)
关键词
注意
在 C 编程语言中,goto
语句的限制较少,并且能进入除变长数组或可变修改指针之外的任何变量的作用域。
示例
运行此代码
- #include <iostream>
- struct Object {
- // 非平凡析构函数
- ~Object() { std::cout << "d"; }
- };
- struct Trivial {
- double d1;
- double d2;
- }; // 平凡构造函数与析构函数
- int main()
- {
- int a = 10;
- // 使用 goto 循环
- label:
- Object obj;
- std::cout << a << " ";
- a = a - 2;
- if (a != 0) {
- goto label; // 跳出 obj 的作用域,调用 obj 析构函数
- }
- std::cout << '\n';
- // goto 可用于简单地离开多层循环
- for (int x = 0; x < 3; x++) {
- for (int y = 0; y < 3; y++) {
- std::cout << "(" << x << ";" << y << ") " << '\n';
- if (x + y >= 3) {
- goto endloop;
- }
- }
- }
- endloop:
- std::cout << '\n';
- goto label2; // 跳入 n 和 t 的作用域
- int n; // 无初始化器
- Trivial t; // 平凡构造函数/析构函数,无初始化器
- // int x = 1; // 错误:有初始化器
- // Object obj2; // 错误:无平凡析构函数
- label2:
- {
- Object obj3;
- goto label3; // 向前跳,离开 obj3 的作用域
- }
- label3: ;
- }
输出:
- 10 d8 d6 d4 d2
- (0;0)
- (0;1)
- (0;2)
- (1;0)
- (1;1)
- (1;2)
- dd
扩展阅读
Edsger W. Dijkstra 的著名文章《我认为 goto 有害》,呈现了此关键词的大意使用会引入的各种微妙问题的考察。
当前内容版权归 cppreference 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 cppreference .