Namespaces
Variants

goto statement

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
goto - return
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

无条件转移控制权。

当无法通过其他语句将控制转移到目标位置时使用。

目录

语法

attr  (可选) goto label ;

说明

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

参见

C 文档 关于 goto

外部链接

Edsger W. Dijkstra 的著名论文 《Goto 语句有害论》 (原载于《ACM通讯》第11卷第3期,1968年3月,第147-148页),系统阐述了滥用该关键字可能引发的诸多隐晦问题。