goto 语句

出自cppreference.com


 
 
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

參閱

goto 的 C 文檔

外部連結

Edsger W. Dijkstra 的著名文章《我認為 goto 有害》(最初發表於《Letter to Communications of the ACM (CACM)》,卷 11, #3, 1968年三月出版),呈現了此關鍵詞的大意使用會引入的各種微妙問題的考察。