goto 语句

来自cppreference.com
< cpp‎ | language


 
 
C++ 语言
 
 

无条件转移控制流。

当使用其他语句不可能将控制转移到所需位置时使用。

语法

属性 (可选) goto 标号 ;

解释

goto 语句将控制转移到标号所指定的位置。goto 语句必须与它所用的标号 处于相同的函数中,它在标号的前后都可以出现。

如果控制的转移退出了任何自动变量的作用域(例如通过回跳到这种变量声明之前的位置,或向前跳出作为变量作用域的复合语句),那么为所有退出作用域的变量以其构造顺序的逆序调用析构函数。

goto 不能将控制转移到有控制流限制的语句之内,但能将控制转移离开有控制流限制的语句(遵循上述有关作用域中的自动变量的规则)

如果控制被转移进入了任何自动变量的作用域(例如通过向前跳过声明语句),那么程序非良构,除非进入作用域的所有变量拥有以下类型:

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

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

注解

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

关键词

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 -= 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 的作用域
 
    [[maybe_unused]] int n; // 没有初始化式
 
    [[maybe_unused]] Trivial t; // 平凡构造函数/析构函数,没有初始化式
 
//  int x = 1; // 错误:有初始化式
//  Object obj2; // 错误:没有平凡析构函数
 
label2:
    {
        Object obj3;
        goto label3; // 向前跳,离开 obj3 的作用域
    }
 
label3:
    std::cout << '\n';
}

输出:

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

参阅

外部链接

Edsger W. Dijkstra 的著名文章《我认为 goto 有害》(最初发表于《Letter to Communications of the ACM (CACM)》,卷 11, #3, 1968年三月出版),呈现了此关键词的大意使用会引入的各种微妙问题的考察。