命名空间
变体
操作

goto 语句

来自 cppreference.cn
< cpp‎ | 语言
 
 
C++ 语言
 
 

无条件地转移控制。

当使用其他语句无法将控制转移到所需位置时使用。

目录

[编辑] 语法

attr (可选) goto 标签 ;

[编辑] 解释

goto 语句将控制转移到由 标签 指定的位置。goto 语句必须与它引用的 标签 在同一个函数中,它可以出现在标签之前或之后。

如果控制转移退出任何自动变量的作用域(例如,通过向后跳转到这些变量声明之前的点,或者通过向前跳出这些变量作用域的复合语句),则按照构造顺序的相反顺序调用所有作用域已退出的变量的析构函数。

goto 语句不能将控制转移到 控制流受限语句 中,但可以从控制流受限语句中转移控制(遵循上述关于作用域内自动变量的规则)。

如果控制转移进入任何自动变量的作用域(例如,通过向前跳过声明语句),则程序是非良构的(无法编译),除非所有进入其作用域的变量都具有以下类型:

  • 未声明初始化的标量类型
  • 具有平凡默认构造函数和平凡析构函数且未声明初始化的类类型
  • 上述类型之一的 cv 限定版本
  • 上述类型之一的数组

(注意:相同的规则适用于所有形式的控制转移)

[编辑] 注意

在 C 编程语言中,goto 语句的限制较少,可以进入除了可变长度数组或可变修改指针之外的任何变量的作用域。

[编辑] 关键词

goto

[编辑] 示例

#include <iostream>
 
struct Object
{
    // non-trivial destructor
    ~Object() { std::cout << 'd'; }
};
 
struct Trivial
{
    double d1;
    double d2;
}; // trivial ctor and dtor
 
int main()
{
    int a = 10;
 
    // loop using goto
label:
    Object obj;
    std::cout << a << ' ';
    a -= 2;
 
    if (a != 0)
        goto label;  // jumps out of scope of obj, calls obj destructor
    std::cout << '\n';
 
    // goto can be used to efficiently leave a multi-level (nested) loops
    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; // jumps into the scope of n and t
 
    [[maybe_unused]] int n; // no initializer
 
    [[maybe_unused]] Trivial t; // trivial ctor/dtor, no initializer
 
//  int x = 1;   // error: has initializer
//  Object obj2; // error: non-trivial dtor
 
label2:
    {
        Object obj3;
        goto label3; // jumps forward, out of scope of obj3
    }
 
label3:
    std::cout << '\n';
}

输出

10 d8 d6 d4 d2
(0,0)
(0,1)
(0,2)
(1,0)
(1,1)
(1,2)
 
d
d

[编辑] 参阅

C 文档 关于 goto

[编辑] 外部链接

Edsger W. Dijkstra 的著名论文《Goto Considered Harmful》(最初发表于“Letter to Communications of the ACM (CACM)”, vol. 11 #3, 1968年3月, pp. 147-148.),对不谨慎使用此关键词可能引入的许多微妙问题进行了调查。