goto 文
提供: cppreference.com
制御を無条件に転送します。
他の文を用いて望みの場所に制御を転送することができないときに使用されます。
構文
attr(オプション) goto label ;
|
|||||||||
説明
goto 文はラベルによって指定された場所に制御を転送します。 goto 文は参照先の label と同じ関数内でなければなりません。 ラベルの前に現れても後に現れても構いません。
制御の転送が何らかの自動変数のスコープを終了する (例えばそのような変数の宣言より前の点への後方ジャンプや、変数のスコープを構成している複文から抜ける前方ジャンプによって) 場合は、スコープが終了するすべての変数について、それらの構築の順序と逆の順序で、デストラクタが呼ばれます。
goto 文は try ブロックや catch 節の内側に制御を転送することはできませんが、 try ブロックや catch 節の外側に制御を転送することはできます (スコープ内の自動変数の関する前述のルールに従います)。
制御の転送が何らかの自動変数のスコープに入る (例えば宣言文を飛び越える前方へのジャンプによって) 場合、プログラムは ill-formed です (コンパイルできません)。 ただし、スコープに入るすべての変数が以下のいずれかである場合は除きます。
1) 初期化子なしで宣言されたスカラー型。
2) 初期化子なしで宣言された、トリビアルなデフォルトコンストラクタとトリビアルなデストラクタを持つクラス型。
3) 上記のいずれかの cv 修飾されたバージョン。
4) 上記のいずれかの配列。
(ノート: すべての形式の制御の転送に同じルールが適用されます)
キーワード
ノート
C 言語では、 goto 文の制約はもっと少なく、可変長配列または可変修飾ポインタ以外のあらゆる変数のスコープに入ることができます。
例
Run this code
#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” は、このキーワードを不注意に使うことによって生じる多くの微妙な問題の概説を提示します。
関連項目
goto の C言語リファレンス
|