goto
はほぼ一般的に推奨されていません。このステートメントを使用する価値はありますか?
コメント
回答
これはStackOverflowで何度か議論されており、Chris Gillum はgoto
の可能な使用法を要約しています:
関数を正常に終了する
多くの場合、関数では、リソースを割り当てて、複数の場所で終了する必要がある場合があります。プログラマーは、関数の最後にリソースクリーンアップコードを配置することでコードを簡略化できます。関数のすべての”出口ポイント”はクリーンアップラベル。このように、関数のすべての”出口点”でクリーンアップコードを記述する必要はありません。
ネストされたループを終了する
ネストされたループに入っていて、すべてのループであるgotoを使用すると、breakステートメントやif-checkよりもはるかにクリーンでシンプルになります。
低レベルのパフォーマンスの向上
これはパフォーマンスクリティカルなコードでのみ有効ですが、gotoステートメントは非常に高速に実行され、関数内を移動するときにブーストを与えることができます。ただし、コンパイラは通常、gotoを含むコードを最適化できないため、これは両刃の剣です。
他の多くの人が主張するように、私は主張します。 、これらすべての場合において、goto
の使用は、自分でコーディングしたコーナーから抜け出すための手段として使用され、通常、リファクタリングできるコードの症状です。 。
コメント
- 最初の問題は、現代語の
finally
ブロックによって非常にうまく解決されます。 2つ目は、ラベル付きのbreak
によって解決されます。ただし、’ Cでスタックしている場合は、goto
は、これらの問題をエレガントに解決する唯一の方法です。 - 非常に良い点です。Javaが複数レベルのループから抜け出す方法が好きです
- @ Chinmay-最終的にブロックのみ1)それらを備えた最新の言語とb)オーバーヘッドを許容できる(例外処理にはオーバーヘッドがあります)に適用されます。 )つまり、
finally
の使用は、これらの条件下でのみ有効です。非常にまれですが、gotoが進むべき道である有効な状況があります。 - わかりました…
break 3
とbreak 3
の違いは何ですか。 div id = “778642721b”>
およびgoto myLabel
。ああ、’はまさにキーワードです。break
、continue
、または同様のキーワードを使用している場合は、実際にはgoto
を使用しています。 (for, while, foreach, do/loop
を使用している場合は、条件付きgotoを使用しています。)
回答
高レベルの制御フロー構造は、問題領域の概念に対応する傾向があります。 if / elseは、何らかの条件に基づく決定です。ループは、いくつかのアクションを繰り返し実行することを示しています。 breakステートメントでさえ、「これを繰り返し行っていましたが、今は停止する必要があります」と述べています。
一方、gotoステートメントは、実行中のプログラムの概念に対応する傾向があり、問題のあるドメイン。 プログラム内の指定されたポイントで実行を継続するように指示されています。コードを読んでいる人は、問題のドメインに関してそれが何を意味するのかを推測する必要があります。
もちろん、すべての高レベルの構造は、gotoと単純な条件分岐の観点から定義できます。 。それは、彼らが単に変装したゴトであるという意味ではありません。それらを制限付きのgotoと考えてください。これは、それらを便利にする制限です。breakステートメントは、囲んでいるループの終わりへのジャンプとして実装されますが、次のように考える方がよいでしょう。ループ全体で動作します。
他の条件がすべて同じであれば、問題のドメインの構造を反映した構造のコードは、読みやすく、保守しやすい傾向があります。
gotoステートメントは絶対に必要です(その効果には定理があります)が、それが最も悪い解決策になる場合があります。言語がサポートする上位レベルの構造に応じて、言語ごとに異なります。
たとえば、Cでは、gotoが適切な3つの基本的なシナリオがあると思います。
- ネストされたループから抜け出す。言語にラベル付きのbreakステートメントがある場合、これは不要です。
- エラーやその他の予期しないイベントが発生した場合に、一連のコード(通常は関数本体)から抜け出します。 。言語に例外がある場合、これは不要です。
- 明示的な有限状態マシンを実装します。この場合(そして、この場合のみ)、gotoは問題ドメインの概念に直接対応し、ある状態から指定された別の状態に移行します。現在の状態は、コードのどのブロックが現在実行されているかによって表されます。 。
一方、明示的な有限状態マシンは、ループ内のswitchステートメントを使用して実装することもできます。これには、すべての状態がコード内の同じ場所から始まるという利点があります。これは、たとえばデバッグに役立ちます。
適度に現代的な言語(if /をサポートする言語)でのgotoの主な用途else and loops)は、「言語から欠落している制御フロー構造をシミュレートすることです。
コメント
- これは実際にはこれまでのところ最良の答えです。 –かなり驚くべきことに、1年半前の質問の場合:-)
- +1から”これまでのベストアンサー”。—“かなり現代的な言語(if / elseとループをサポートする言語)でのgotoの主な用途は、制御フローをシミュレートすることです。 ‘が言語から欠落していることを構築します。”
- スイッチステートメントステートマシンでは、制御値は実際には
goto
です。SSSM’は、多くの場合、使用するのに適した構造です。実行構造からSM状態を分離しますが、’実際には” gotos “。 - “他の条件がすべて同じであれば、問題のドメインの構造を反映した構造のコードは、読みやすく、保守しやすい傾向があります。” 私は’これを長い間完全に知っていましたが、他の方法で正確に伝えるための言葉がありませんでしたプログラマーは実際に理解することができ、実際に理解するでしょう。
- “構造化プログラムの定理”は、明確に示す傾向があるため、私を楽しませてくれます。構造化プログラミングステートメントを使用してgotoをエミュレートすることは、gotoを使用するよりもはるかに読みにくいことを指摘してください!
回答
確かにそれはプログラミング言語に依存します。 goto
が物議を醸している主な理由は、コンパイラーがそれをあまりにも自由に使用できるようにしたときに生じる悪影響のためです。たとえば、goto
を使用して、初期化されていない変数にアクセスしたり、さらに悪いことに、別のメソッドにジャンプして呼び出しを混乱させたりできる場合、問題が発生する可能性があります。スタック。無意味な制御フローを禁止するのはコンパイラの責任です。
Javaは、goto
を完全に禁止することにより、この問題を「解決」しようとしました。ただし、Javaではreturn
をfinally
ブロック内で使用できるため、誤って例外が飲み込まれてしまいます。同じ問題がまだあります:コンパイラはその仕事をしていません。言語からgoto
を削除しても修正されていません。
C#では、goto
は
、continue
、try/catch/finally
、return
。初期化されていない変数を使用したり、finallyブロックからジャンプしたりすることはできません。コンパイラは文句を言います。これは、無意味な制御フローについて述べたように、実際の問題を解決するためです。 goto
は、明確な割り当ての分析やその他の妥当なコンパイラチェックを魔法のようにキャンセルしません。
コメント
- あなたのポイントは、C#’ s
goto
は悪ではないということですか?もしそうなら、それは、C#…
だけでなく、goto
構造を持つ日常的に使用されるすべての現代語に当てはまります。回答
はい。ループが数レベルの深さでネストされている場合、goto
は、内側のループからエレガントに抜け出すための唯一の方法です。もう1つのオプションは、フラグを設定し、そのフラグが条件を満たす場合に各ループから抜け出すことです。これは本当に醜く、かなりエラーが発生しやすいです。このような場合、goto
の方が優れています。
もちろん、Javaのbreak
ステートメントも同じです。ただし、コード内の任意のポイントにジャンプすることはできません。これにより、goto
を邪魔するものを許可せずに問題を適切に解決できます。
コメント
- gotoは決してエレガントな答えではありません。ループが数レベルの深さでネストされている場合、問題は、マルチネストされたループを回避するためのコードの設計に失敗したことです。プロシージャ呼び出しはそうではありません。敵。(” Lambda:The Ultimate … “の論文を読んでください。)gotoを使用して、いくつかネストされたループから抜け出します。レベルの深さは、開いた複数の破壊にバンドエイドをかけています。それは単純かもしれませんが、’正しい答えではありません。
- そしてもちろん、そこに深くネストされたループが必要な場合、決して奇妙なケースではありませんか?優れたプログラマーであることはルールに従うだけでなく、いつルールを破るかを知ることについても。
- @ JohnR.Strohm決して言わないでください。プログラミングで”決して”のような用語を使用する場合、’は明らかに取り扱われていません。コーナーケース、最適化、リソースの制約などがあります。深くネストされたループでは、 goto は、ループを終了するための最もクリーンでエレガントな方法です。 ‘コードをリファクタリングした量は関係ありません’。
- @ JohnR.Strohm:2番目に見逃したものVB.NETからC#への切り替えに関する機能:
Do
ループ。どうして?深いブレークが必要な1つのループをDo
ループに変更し、Exit Do
と入力すると’いいえGoTo
。ネストされたループは常に発生します。スタックの破壊は、一部の確率で発生します。 - @ JohnR.Strohm ” gotoと言う唯一の理由は、決してエレガントな答えではありません”は、gotoは決してエレガントな答えではないことを決心したためです。したがって、gotoを使用したソリューションは、エレガントな答えにはなり得ません。
回答
落胆のほとんどは、「60年代初頭」の無差別な力に説得力を持っていたジクストラ神の周りに作成された一種の「宗教」から来ています。 :
- コードのブロックにジャンプします
- 関数は最初から実行されません
- ループは最初から実行されません
- スキップされた変数の初期化
- クリーンアップの可能性なしにコードのブロックからジャンプします。
これはgoto
現代語のステートメント。その存在は単にcrをサポートするためです。言語で提供されているもの以外のコード構造の使用。
特に、上記の最初の要点は許可されなくなり、2番目の要点はクリーンアップされます(goto
スタックが適切に巻き戻され、すべての適切なデストラクタが呼び出されるブロック)
この回答を参照して、コードがどのように機能しないかを知ることができますgotoの使用は判読できない場合があります。問題はgoto自体ではなく、その悪用です。
if
を使用せずに、。もちろん、読みにくく、不器用で不必要に複雑に見えます。
しかし、問題はfor
ではありません。それは私です。
break
、continue
、throw
、
などは、マスカレード goto
が、ジクストラリアンの熱狂者のシミターから逃げ出すことに注目しています。現代の言語の発明から50年後-まだ彼らの囚人を望んでいます。彼らは、ダイクストラが話していることを忘れ、彼のメモのタイトル(GOTOは有害であると見なされ、それは彼のタイトルでさえありませんでした:編集者によって変更されました)を覚えているだけで、手紙は順番に配置されます。
2011年:goto
がGOTO
ダイクストラの声明は説得力がありました。
コメント
- “休憩など、続けてください、throw、bool required = true; while(needed){…}などは仮面舞踏会以上のことを指摘しています”私はそれに同意しません’。 “休憩などは制限 goto “などにしたいと思います。 gotoの主な問題は、通常は強力すぎることです。現在のgotoがDijkstra ‘よりも強力でない限り、あなたの答えは私には問題ありません。
- @MuhammadAlkarouri:私は完全に同意します。私のコンセプトを正確に表現するためのより良い表現を見つけました。私のポイントは、これらの制限が適用できない場合があり、必要な制限の種類が言語にないことです。次に、より専門的ではない、より”強力な”が、回避策を可能にします。たとえば、Java
break n
はC ++では使用できないため、escape
divであっても、goto escape
です。 >はn-pleループのすぐ外にある必要はありません。
回答
ここにある奇妙なgotoまたは、関数に対してローカルである限り、読みやすさを著しく損なうことはめったにありません。このコードでは、やや珍しい制御構造の使用を必要とする異常なことが起こっているという事実に注意を向けることで、多くの場合、メリットがあります。 。
(ローカル)gotoが読みやすさを著しく損なう場合は、通常、gotoを含む関数が複雑になりすぎていることを示しています。
最後にgotoを入力しました。 Cコードの一部は、インターロックループのペアを構築することでした。これは、「許容可能な」goto使用の通常の定義には適合しませんが、結果として、関数は大幅に小さくなり、明確になりました。 gotoを回避するには、DRYの特に厄介な違反が必要でした。
コメント
- これに対する答えは、古い
レイ’のポテトチップス”スローガン:”賭けて’ 1つだけ食べることはできません”。あなたの例では、2つの”連動”があります(それが意味するものは何でも、私は’それは’ tかわいい)ループではないことを賭けて、gotoはあなたに安いアウトを与えました。バスにぶつかった後、そのコードを変更しなければならない保守担当者はどうですか?後藤は彼の人生を楽にするのか、それとも難しくするのか?これらの2つのループを再考する必要がありますか?
回答
この問題全体が吠えているケースだと思います間違ったツリー。
GOTO自体は私には問題がないように見えますが、実際の罪の症状であることがよくあります。スパゲッティコードです。
GOTOが原因である場合フロー制御ラインの主要な交差は、悪い期間です。フロー制御ラインを交差しない場合は、無害です。中間のグレーゾーンには、ループベイルアウトなどがありますが、正当なグレーのケースすべてをカバーする構造を追加していない言語がまだいくつかあります。
実際に使用しているのは私が見つけた唯一のケースです。多くの場合、決定点がループの真ん中にあるループの場合です。 「重複したコード、フラグ、またはGOTOのいずれかが残っています。GOTOソリューションは3つのうちで最も優れていると思います。ここではフロー制御ラインの交差はなく、無害です。
コメント
- あなたがほのめかすケースは、「ループと半分」または「Nプラス半分のループ」と呼ばれることがあり、(言語で許可されている場合。他の場合、途中でループからジャンプするのは、通常、
goto
がなければ簡単です。 )。 - (残念ながら、ほとんどの言語ではループへのジャンプが禁止されています。)
- @KonradRudolph:”ループ
GOTOでは、他にジャンプするループ構造はありません。
-
goto
はここで制御フローが実行されない’ T FIT NORMAL STRUCTURED-PROGRAMMINGパターン。構造化プログラミングパターンに適合する制御フローは、そうでないものよりも推論が容易であるため、’可能であれば、そのようなパターンの使用を試みる必要があります。コードがそのようなパターンに適合する場合は、’ ‘ tと叫ぶべきではありません。一方、コードが実際にそのようなパターンに適合しない場合は’、コードが実際に適合しない場合にコードが適合するふりをするよりも、それについて叫ぶ方がよい場合があります’ t。 - @supercatさて、あなたが自分でスケジュールを書いたとしたら、風があなたの手からそれを吹き飛ばします。あなたの論理によれば、あなたはそれを取得するべきではありません’あなたのスケジュールを追いかけることはあなたのスケジュールに’なかったからです。
回答
はい、gotoを使用して開発者のエクスペリエンスを向上させることができます: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
ただし、他の強力なツール(ポインター、多重継承など)と同様に、規律を保つ必要があります。それを使用します。リンクで提供されている例では、PHPを使用しています。これにより、goto構造の使用が同じ関数/メソッドに制限され、新しい制御ブロック(loop、switchステートメントなど)にジャンプする機能が無効になります。
回答
言語によって異なります。たとえば、これはまだCOBOLプログラミングで広く使用されています。私はBarionet 50デバイスにも取り組んできました。このデバイスのファームウェアプログラミング言語は、もちろんGotoを使用する必要がある初期のBASICダイアレクトです。
回答
goto
は、レガシーアセンブラコードをCに移植するときに役立つ場合があります。最初に、命令-アセンブラのbranch
命令の代わりにgoto
を使用して、命令ごとにCに変換すると、非常に高速な移植が可能になります。
コメント
- 正解ですが、
goto
に対する反論の1つは、コンパイラの最適化を妨げることです。 - @Sapphire_Brick:多くのコンパイラ最適化は、特定の実行パターンを中心に設計されています。実行するタスクがサポートされている実行パターンに適合しない場合は、’ “妨害”最適化はできない場合があります悪いことです。
回答
いいえと主張します。それらは常に、gotoが解決に使用されている問題に固有のツールに置き換える必要があります(言語で使用できない場合を除く)。たとえば、breakステートメントと例外は、以前にgotoで解決されたループエスケープの問題を解決します。エラー処理。
コメント
- I ‘ dは、言語に両方がある場合 / i>これらの機能、
goto
は通常、これらの言語にはありません。 - ただし、’それらが必要なのか、それとも人々が’必要ないと思っているのか?
- あなたの意見は大げさです。
goto
は、非常に問題のあるドメインセマンティクスに最も近いものであり、それ以外はダーティハックになります。 - @ SK-logic:私は’ ” bigoted “という言葉はあなたが思っていることを意味するとは思わない。
- @キース、
彼または彼女自身の意見や偏見に不寛容に専念”-それは’私がこの後藤バッシング目隠しロットで、一貫してここを観察してください。 “常に交換する必要があります”は熱狂的です’少なくとも言葉。適切で健全な意見に近いものはありませんが、純粋な偏見にすぎません。この”常に”は、代替意見のためのスペースを残していません。参照してください。
回答
いいえと言います。 GOTOを使用する必要がある場合は、コードを再設計する必要があると思います。
コメント
- たぶん、あなたは’理由を提供していません
- ダイクストラは、数十年前に詳細に理由を提供しました。
- ただの教義。理由はありません。注:Djikstraは有効な理由ではありません。’ 60年代初期のBASICまたはFORTRANGOTOステートメントを参照していました。彼らは(それらの力と比較して)今日の本当に貧血とは何の関係もありません。
- @EmilioGaravagliaええと、今日でも当てはまる彼の推論の一部は、多くのゴトへの道を使ってスパゲッティコードを書くのが非常に簡単であるということです。 ただし、そのロジックでは、
number of gotos needed to create problems
と同じ数のポインタを使用すると同様の混乱が生じるため、’ポインタを使用しないでください。
goto
はCPUが最終的に行うことですが、ターゲットにマークがないため、人間が理解して抽象化する必要があるものではうまく機能しません。終わり。 IntercalCOMEFROM
と比較してください。goto
は必要ありません。これは、状態遷移のセマンティクスに最も近いものであるため、命令型言語でそれらを実装するための最も合理的な方法です。また、宛先はソースからかなり離れている可能性があり、’読みやすさを妨げることはありません。そのようなコードの私のお気に入りの例はD.Eです。 Knuth ‘によるアドベンチャーゲームの実装。