名前空間
変種
操作

goto 文

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
goto - return
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (C++20未満)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
ラベル
label : statement
式文
expression ;
複文
{ statement... }
選択文
if
switch
繰り返し文
while
do-while
for
範囲 for(C++11)
ジャンプ文
break
continue
return
goto
宣言文
declaration ;
try ブロック
try compound-statement handler-sequence
トランザクショナルメモリ
synchronized, atomic_commit など(TM TS)
 

制御を無条件に転送します。

他の文を用いて望みの場所に制御を転送することができないときに使用されます。

目次

[編集] 構文

attr(オプション) goto label ;

[編集] 説明

goto 文はラベルによって指定された場所に制御を転送します。 goto 文は参照先の label と同じ関数内でなければなりません。 ラベルの前に現れても後に現れても構いません。

制御の転送が何らかの自動変数のスコープを終了する (例えばそのような変数の宣言より前の点への後方ジャンプや、変数のスコープを構成している複文から抜ける前方ジャンプによって) 場合は、スコープが終了するすべての変数について、それらの構築の順序と逆の順序で、デストラクタが呼ばれます。

goto 文は try ブロックや catch 節の内側に制御を転送することはできませんが、 try ブロックや catch 節の外側に制御を転送することはできます (スコープ内の自動変数の関する前述のルールに従います)。

制御の転送が何らかの自動変数のスコープに入る (例えば宣言文を飛び越える前方へのジャンプによって) 場合、プログラムは ill-formed です (コンパイルできません)。 ただし、スコープに入るすべての変数が以下のいずれかである場合は除きます。

1) 初期化子なしで宣言されたスカラー型。
2) 初期化子なしで宣言された、トリビアルなデフォルトコンストラクタとトリビアルなデストラクタを持つクラス型。
3) 上記のいずれかの cv 修飾されたバージョン。
4) 上記のいずれかの配列。

(ノート: すべての形式の制御の転送に同じルールが適用されます)

[編集] キーワード

goto

[編集] ノート

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 Considered Harmful” は、このキーワードを不注意に使うことによって生じる多くの微妙な問題の概説を提示します。

[編集] 関連項目