[解決済み] gotoを使うと変数が漏れる?
質問
次のことは本当ですか?
goto
はデストラクタなどを呼び出すことなく、コードのビットを飛び越えるというのは本当ですか?
など。
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
ウォンツ
x
が漏れるのでは?
どのように解決するのですか?
<サブ 警告です。 この回答は C++ に関連するものです のみ Cではルールはかなり異なっています。
しない
x
が漏れるのでは?
いいえ、絶対にありません。
というのは神話です。
goto
は C++ の組み込みのスコープ機構を上書きできる低レベルの構成要素であるというのは迷信です。(どちらかというと、それは
longjmp
がこれに該当する可能性があります)。
ラベルで "悪いこと" をしないようにする次のような仕組みを考えてみましょう(これには
case
ラベルを含みます)。
1. ラベルの範囲
関数をまたいでジャンプすることはできません。
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
// error: label 'lol' used but not defined
[n3290: 6.1/1]:
[ラベルのスコープは、そのラベルが表示される関数です。 である。[..]
2. オブジェクトの初期化
オブジェクトの初期化を飛び越えることはできません。
int main() {
goto lol;
int x = 0;
lol:
return 0;
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘int x’
ジャンプした場合 <項目 裏 オブジェクトを初期化した後 オブジェクトの前のインスタンスが破棄されます。 :
struct T {
T() { cout << "*T"; }
~T() { cout << "~T"; }
};
int main() {
int x = 0;
lol:
T t;
if (x++ < 5)
goto lol;
}
// Output: *T~T*T~T*T~T*T~T*T~T*T~T
[n3290: 6.6/2]:
[...] ループの外、ブロックの外、または初期化された変数の自動保存期間を過ぎた後の転送には 自動保存期間を持つ初期化された変数の過去への転送は、自動保存期間を持つオブジェクトの破壊を伴います。 自動保存期間を持つオブジェクトの破壊を伴います。 スコープ内にあり、転送された時点ではスコープ内にない自動保存期間を持つオブジェクトの破壊を伴います。 に転送される。[..]
オブジェクトのスコープに飛び込むことは、たとえ明示的に初期化されていなくてもできない。
int main() {
goto lol;
{
std::string x;
lol:
x = "";
}
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘std::string x’
... ただし ある種のオブジェクト を除いて、これらは複雑な構造を必要としないため、言語が関係なく処理することができます。
int main() {
goto lol;
{
int x;
lol:
x = 0;
}
}
// OK
[n3290: 6.7/3]:
ブロックへの転送は可能ですが、初期化を伴う宣言を回避する方法はありません。 初期化を伴う宣言を迂回するような方法で プログラムとして 自動保存期間を持つ変数がスコープにないところから、スコープにあるところまでジャンプするプログラム スコープ内にないところから、スコープ内にあるところへジャンプするようなプログラムは その変数がスカラー型であり,クラス型であり,些細なデフォルトコンストラクタと些細なデストラクタがある場合 コンストラクタとデストラクタを持つクラス型,これらの型の cv-qualified バージョン,または,これらの型の配列でない限り,自動保存期間を持つ変数がスコープ内に存在することは,不正確です. これらの型の cv-qualified バージョン,または前述の型の 1 つを持つ配列で,イニシャライザなしで宣言されている場合を除きます. イニシャライザなしで宣言されています.[..]
3. ジャンプは他のオブジェクトのスコープに従う
同様に、自動保存期間を持つオブジェクト
は
ではなく
goto
struct T { T() { cout << "*T"; } ~T() { cout << "~T"; } }; int main() { { T t; goto lol; } lol: return 0; } // *T~T
スコープから出るとき(どのように達成されたとしても),オブジェクト 自動保存期間(3.7.3)を持つオブジェクトで、そのスコープで構築されたものは を持つオブジェクトは,その構築の逆の順序で破壊される。 [..]
結論
上記の仕組みにより
[n3290: 6.6/2]:
は言語を壊させないようにします。
もちろん、だからといって自動的に
goto
を使うべきだということではありませんが、これは
は
一般的な神話が人々に信じさせるほどには、quot; evil" ではないということを意味します。
関連
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み] 配列のベクトルを扱う正しい方法
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] switch文の中で変数を宣言してはいけないのはなぜですか?
-
[解決済み】Javaにgoto文はあるのか?
-
[解決済み] C++でvoid関数から抜けるにはどうしたらいいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み] 既に.objで定義されている-二重包含はない
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み] CまたはC++の良いゴトの例 [終了しました]。