質問

goto ほとんど普遍的に落胆しています。このステートメントを使用する価値はありますか?

役に立ちましたか?

解決

これは、スタックオーバーフローとクリスギルムで何度か議論されています の可能な用途を要約しました goto:

関数をきれいに終了します

多くの場合、関数では、リソースを割り当て、複数の場所で終了する必要があります。プログラマーは、関数のすべてのすべての「終了ポイント」にリソースクリーンアップコードを関数の最後に配置することにより、クリーンアップラベルを取得することで、コードを簡素化できます。このようにして、関数のすべての「終了ポイント」でクリーンアップコードを記述する必要はありません。

ネストされたループを終了します

ネストされたループにいて、脱出する必要がある場合 すべて ループ、gotoは、これをブレークステートメントやif-checksよりもはるかにクリーンでシンプルにすることができます。

低レベルのパフォーマンスの改善

これはパフルクリティカルコードでのみ有効ですが、GOTOステートメントは非常に迅速に実行され、関数を移動するときにブーストを与えることができます。ただし、これは両刃の剣です。なぜなら、コンパイラは通常、GOTOSを含むコードを最適化できないためです。

他の多くの人が主張するように、これらのすべての場合において、の使用は goto コーディングされたコーナーから抜け出すための手段として使用されており、一般的にはリファクタリングできるコードの症状です。

他のヒント

高レベルの制御フローコンストラクトは、問題ドメインの概念に対応する傾向があります。 if/elseは、何らかの条件に基づいた決定です。ループは、何らかのアクションを繰り返し実行するように言っています。ブレイクの声明でさえ、「私たちはこれを繰り返しやっていましたが、今は止める必要があります」と書かれています。

一方、GOTOの声明は、問題ドメインではなく、実行中のプログラムの概念に対応する傾向があります。指定されたポイントで実行を継続すると述べています プログラムで. 。コードを読んでいる人が必要です 推測します それが問題ドメインに関して何を意味するのか。

もちろん、すべての高レベルのコンストラクトは、GOTOSと単純な条件付きブランチの観点から定義できます。それは、彼らが単に変装しているだけであるという意味ではありません。それらを考えてください 制限付き gotos-そしてそれはそれらを有用にする制限です。ブレークステートメントは、囲みながらループの終わりまでのジャンプとして実装されますが、ループ全体で動作すると考えられています。

他のすべてが平等であり、構造が問題ドメインの構造を反映しているコードは、読みやすく維持しやすい傾向があります。

gotoの声明が絶対に必要な場合はありません(ある 定理 その結果、)、しかし、それが最も悪い解決策になる可能性がある場合があります。これらのケースは、言語がサポートする高レベルの構成によって言語ごとに異なります。

たとえば、Cでは、GOTOが適切である3つの基本的なシナリオがあると思います。

  1. ネストされたループから脱出します。これは、言語にラベルの付いたブレークステートメントがある場合、不要です。
  2. エラーやその他の予期しないイベントの場合、一連のコード(通常は関数本文)から救済します。言語に例外があれば、これは不要です。
  3. 明示的な有限状態マシンの実装。この場合(そして、この場合にのみ)、GOTOは問題ドメインの概念に直接対応し、ある状態から特定の他の状態に移行します。 。

一方、明示的な有限状態マシンは、ループ内のスイッチステートメントを使用して実装することもできます。これには、すべての状態がコード内の同じ場所から始まるという利点があり、たとえばデバッグに役立ちます。

合理的に近代的な言語でのGOTOの主な使用(If/elseおよびループをサポートするもの)は、言語に欠けているコントロールフロー構成をシミュレートすることです。

確かにそれはプログラミング言語に依存します。主な理由 goto 物議を醸すのは、コンパイラがあまりにも自由に使用できるときに発生する悪影響のためです。たとえば、問題が発生する可能性があります。 goto これで、未定化変数にアクセスするか、さらに悪いことに、別の方法にジャンプしてコールスタックを混乱させるようになりました。非センシックコントロールフローを許可することは、コンパイラの責任である必要があります。

Javaは、許可することでこの問題を「解決」しようとしました goto 全体的に。ただし、Javaで使用できます return 内側 finally ブロックされるため、例外が不注意に飲み込まれます。同じ問題がまだあります。コンパイラは仕事をしていません。削除 goto 言語からはそれを修正していません。

C#で、 goto 同じくらい安全です break, continue, try/catch/finallyreturn. 。未解決の変数を使用することはできませんし、最終的なブロックなどから飛び出すこともできません。コンパイラは文句を言います。これは、それが解決するからです 本物 問題は、私が無意味な制御フローを言ったようなものです。 goto 明確な割り当て分析やその他の合理的なコンパイラチェックを魔法のようにキャンセルしません。

はい。ループがいくつかのレベルの深さでネストされている場合、 goto それは それだけ 内側のループからエレガントに壊れる方法。もう1つのオプションは、そのフラグが条件を満たしている場合、フラグを設定して各ループから抜け出すことです。これは本当に醜く、かなりエラーが発生しやすいです。これらの場合、 goto 単に優れています。

もちろん、Javaのラベル break ステートメントは同じことをしますが、コードの任意のポイントにジャンプすることはできません。 goto 悪の。

落胆のほとんどは、60年代初頭にそれが無差別の力について魅力的だったAroud God djikstraを作成した一種の「宗教」を形成します。

  • どこでもコードのブロックにジャンプします
    • 最初から実行されない関数
    • ループは最初から実行されません
    • 変数の初期化をスキップしました
  • クリーンアップの可能性がなく、コードブロックから飛び降ります。

これはそれ以上のこととは何の関係もありません goto 現代言語の声明。その存在は、単に提供された言語以外のコード構造の作成をサポートするだけです。

特に、上記の最初の主要なポイントはもう許可されており、2番目はクリーニングされます(あなたが goto ブロックから、スタックは適切に解放され、すべての適切なデストラクタと呼ばれます)

参照できます この答え gotoを使用しないことでさえ、どのようにコードを使用しても読み取れないことを知ることができます。問題はGOTO自体ではなく、それの悪い使用です。

使用せずにプログラム全体を書くことができます if, 、 ただ for。もちろん、それは十分に読みやすくなく、不器用で不必要に複雑に見えます。

しかし、問題はそうではありません for. 。それは私です。

のようなもの break, continue, throw, bool needed=true; while(needed) {...}, 、などは以上に注目しています 仮面舞踏会 goto 現代のラゲージの発明から50年後のdjikstrarianの熱狂者のサイミターから逃げるために、まだ囚人を望んでいます。彼らはDjikstraが話していることを忘れていました、彼らは彼のメモのタイトルを覚えています(Gotoは有害と見なされ、それは彼のONWのタイトルでさえありませんでした:それは編集者によって変更されました)、そしてそれらの4を持っているすべてのContructを非難し、Bash、Bash、Blame順番に配置された文字。

2011年です:それを理解する時が来ました goto 対処することに注目しています GOTO 声明Djikstraは説得力がありました。

あちこちに奇妙なことは、それが関数のローカルである限り、読みやすさを大きく害することはめったにありません。しばしば、このコードでは、やや珍しい制御構造を使用する必要があるという珍しいことが起こっているという事実に注意を喚起することで利益を得ることができます。

(ローカル)gotosが読みやすさを大幅に傷つけている場合、それは通常、gotoを含む関数が複雑すぎたことの兆候です。

私が最後にCコードに入れたのは、一対のインターロックループを構築することでした。 「許容可能な」GOTOの使用の通常の定義には適合しませんが、その結果、機能は大幅に小さく、より明確になりました。 GOTOを避けるために、ドライの特に厄介な違反が必要だったでしょう。

この問題全体は、間違った木をbarえるケースだと思います。

GoToは私には問題がないようには見えませんが、むしろ実際の罪の症状であるSpaghettiコードです。

gotoがフロー制御ラインの大きな交差を引き起こす場合、それは悪い期間です。フロー制御ラインを越えない場合、それは無害です。その間のグレーゾーンには、ループ救済のようなものがありますが、すべての合法的な灰色のケースをカバーするコンストラクトを追加していない言語がまだあります。

長年にわたって実際に使用している唯一のケースは、決定点がループの中央にあるループの場合です。重複したコード、フラグ、またはgotoのいずれかが残っています。 GoToソリューションは3つの中で最高だと思います。ここにはフロー制御ラインの交差はありません、それは無害です。

はい、GOTOは開発者の経験に利益をもたらすために使用できます。http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

ただし、強力なツール(ポインター、多重継承など)と同様に、それを使用して規律する必要があります。リンクで提供されている例はPHPを使用します。これにより、GOTOコンストラクトの使用が同じ関数/メソッドに制限され、新しいコントロールブロックにジャンプする機能が無効になります(例えば、ループ、スイッチステートメントなど)

言語に依存します。たとえば、COBOLプログラミングではまだ広く使用されています。また、ファームウェアプログラミング言語は初期の基本的な方言であるBarionet 50デバイスにも取り組んできました。もちろん、GOTOを使用する必要があります。

私はノーと言うでしょう。 GOTOを使用する必要があることがわかった場合は、コードを再設計する必要があると確信しています。

goto レガシーアセンブラーコードをCに移植する場合に役立つ場合があります。最初の例では、cへの指示ごとの変換を使用して、 goto アセンブラーの代替品として branch 指示は、非常に迅速な移植を可能にすることができます。

私はノーを議論します。それらは常に、GOTOが解決するために使用されている問題により特有のツールに置き換える必要があります(あなたの言語で利用できない場合を除きます)。たとえば、ブレークステートメントと例外は、以前にループエスケープとエラー処理のgotoが解決した問題に対して解決します。

ライセンス: CC-BY-SA帰属
所属していません softwareengineering.stackexchange
scroll top