goto
est presque universellement déconseillé. Est-ce que lutilisation de cette instruction en vaut la peine?
Commentaires
Réponse
Cela a été discuté à plusieurs reprises sur Stack Overflow, et Chris Gillum a résumé les utilisations possibles de goto
:
Quitter proprement une fonction
Souvent, dans une fonction, vous pouvez allouer des ressources et devoir quitter à plusieurs endroits. Les programmeurs peuvent simplifier leur code en mettant le code de nettoyage des ressources à la fin de la fonction, tous les » points de sortie » de la fonction vont létiquette de nettoyage. De cette façon, vous n’avez pas à écrire de code de nettoyage à chaque » point de sortie » de la fonction.
Sortie des boucles imbriquées
Si vous « êtes dans une boucle imbriquée et que vous devez sortir de toutes boucles, un goto peut rendre cela beaucoup plus propre et plus simple que les instructions break et les if-checks.
Améliorations des performances de bas niveau
Ceci nest valable que dans le code critique pour les performances, mais les instructions goto sexécutent très rapidement et peuvent vous donner un coup de pouce lorsque vous vous déplacez dans une fonction. Ceci est une épée à double tranchant, cependant, car un compilateur ne peut généralement pas optimiser le code qui contient des gotos.
Je « dirais, comme beaucoup dautres le diraient , que dans tous ces cas, lutilisation de goto
est utilisée comme un moyen de sortir dun coin dans lequel on sest codé, et est généralement un symptôme de code qui pourrait être refactorisé .
Commentaires
- Le premier problème est résolu très clairement par des blocs
finally
dans les langues modernes, et la seconde est résolue parbreak
s. Si vous ‘ êtes bloqué avec C cependant,goto
est à peu près le seul moyen de résoudre ces problèmes avec élégance. - Très bons points. Jaime la façon dont Java permet de sortir de plusieurs niveaux de boucles
- @Chinmay – enfin bloque uniquement sappliquent à 1) les langues modernes qui les ont et b) vous pouvez tolérer la surcharge (la gestion des exceptions a une surcharge. ) Autrement dit, lutilisation de
finally
nest valide que dans ces conditions. Il y a des situations très rares, mais valables, où un goto est la voie à suivre. - Daccord, les gens … quelle est la différence entre
break 3
oubreak myLabel
etgoto myLabel
. Oh que ‘ est juste le mot-clé. Si vous utilisezbreak
,continue
ou un mot clé similaire, vous utilisez en fait ungoto
(Si vous utilisezfor, while, foreach, do/loop
, vous utilisez un goto conditionnel.) - À propos des performances de bas niveau – le comportement du processeur moderne peut être difficile à prévoir (pipeline, exécution dans le désordre) donc probablement dans 99% des cas cela ne vaut pas la peine ou même cela pourrait être plus lent. @MatthewWhited: cadrage. Si vous entrez scope à un point arbitraire, il nest pas clair (pour lhomme) quels constructeurs doivent être appelés (le problème existe également en C).
Réponse
Les constructions de flux de contrôle de niveau supérieur ont tendance à correspondre aux concepts du domaine du problème. Un if / else est une décision basée sur une condition. Une boucle dit deffectuer une action à plusieurs reprises. Même une instruction break dit « nous faisions cela à plusieurs reprises, mais maintenant nous devons arrêter ».
Une instruction goto, par contre, tend à correspondre à un concept dans le programme en cours dexécution, pas dans le domaine du problème. Il dit de continuer lexécution à un point spécifié dans le programme . Quelquun qui lit le code doit déduire ce que cela signifie par rapport au domaine du problème.
Bien sûr, toutes les constructions de niveau supérieur peuvent être définies en termes de gotos et de simples branches conditionnelles . Cela ne signifie pas quils sont simplement des gotos déguisés. Considérez-les comme des gotos restreints – et ce sont les restrictions qui les rendent utiles. Une instruction break est implémentée comme un saut à la fin de la boucle englobante, mais il vaut mieux la considérer comme fonctionnant sur la boucle dans son ensemble.
Toutes choses étant égales par ailleurs, un code dont la structure reflète celle du domaine problématique a tendance à être plus facile à lire et à maintenir.
Il ny a aucun cas où une instruction goto est absolument nécessaire (il y a « s un théorème à cet effet), mais il y a des cas où cela peut être la solution la moins mauvaise. Ces cas varient de langue à langue, en fonction des constructions de niveau supérieur prises en charge par le langage.
En C, par exemple, je crois quil existe trois scénarios de base où un goto est approprié.
- Rupture dune boucle imbriquée. Cela ne serait pas nécessaire si le langage avait une instruction break étiquetée.
- Renvoi dun bout de code (généralement un corps de fonction) en cas derreur ou autre événement inattendu . Ce serait inutile si le langage avait des exceptions.
- Implémentation dune machine à états finis explicite. Dans ce cas (et, je pense, seulement dans ce cas), un goto correspond directement à un concept dans le domaine du problème, passant dun état à un autre état spécifié, où létat actuel est représenté par le bloc de code en cours dexécution .
Dun autre côté, une machine à états finis explicite peut également être implémentée avec une instruction switch dans une boucle. Cela présente lavantage que chaque état commence au même endroit dans le code, ce qui peut être utile pour le débogage, par exemple.
Lutilisation principale dun goto dans un langage raisonnablement moderne (celui qui prend en charge if / else and loops) consiste à simuler une construction de flux de contrôle qui « est absente du langage.
Commentaires
- Cest en fait la meilleure réponse à ce jour – assez surprenant, pour une question qui date dun an et demi. 🙂
- +1 à » meilleure réponse à ce jour « . — » Lutilisation principale dun goto dans un langage raisonnablement moderne (celui qui prend en charge if / else et les boucles) est de simuler un flux de contrôle construire que ‘ est absent du langage. »
- Dans la machine à états des instructions de commutation, chaque écriture dans le La valeur de contrôle est en réalité une
goto
. Les SSSM ‘ sont souvent de bonnes structures à utiliser, car elles séparent létat SM de la construction dexécution, mais ils néliminent pas ‘ vraiment » gotos « . - » Toutes choses étant égales par ailleurs, le code dont la structure reflète celle du domaine du problème a tendance à être plus facile à lire et à maintenir. » Je ‘ je le savais complètement depuis longtemps mais je manquais de mots pour le communiquer si précisément dune manière que les autres les programmeurs peuvent et comprendront réellement. Merci pour cela.
- Le » théorème du programme structuré » mamuse, car il tend à démontrer clairement le faites remarquer quutiliser des instructions de programmation structurées pour émuler un goto est beaucoup moins lisible que simplement utiliser un goto!
Answer
Cela dépend sûrement du langage de programmation. La principale raison pour laquelle goto
a été controversée est à cause de ses effets néfastes qui surviennent lorsque le compilateur vous permet de lutiliser trop libéralement. Des problèmes peuvent survenir, par exemple, sil vous permet dutiliser goto
de telle manière que vous pouvez maintenant accéder à une variable non initialisée, ou pire, de sauter dans une autre méthode et de jouer avec lappel empiler. Il devrait être de la responsabilité du compilateur dinterdire les flux de contrôle absurdes.
Java a tenté de «résoudre» ce problème en interdisant complètement goto
. Cependant, Java vous permet dutiliser return
à lintérieur dun bloc finally
et donc de faire avaler une exception par inadvertance.Le même problème est toujours là: le compilateur ne fait pas son travail. La suppression de goto
de la langue ne la pas résolu.
En C #, goto
est aussi sûr que break
, continue
, try/catch/finally
et return
. Il ne vous permet pas d’utiliser des variables non initialisées, il ne vous permet pas de sauter hors d’un bloc finally, etc. Le compilateur se plaindra. Cest parce que cela résout le problème réel , qui est comme je lai dit un flux de contrôle insensé. goto
nannule pas comme par magie lanalyse daffectation définie et dautres vérifications raisonnables du compilateur.
Commentaires
- Votre point est que C # ‘ s
goto
nest pas mauvais? Si tel est le cas, cest le cas pour tous les langages modernes couramment utilisés avec une constructiongoto
, pas seulement C # …
Réponse
Oui. Lorsque vos boucles sont imbriquées sur plusieurs niveaux, goto
est la seule manière de sortir élégamment dune boucle interne. Lautre option est de définir un indicateur et de sortir de chaque boucle si cet indicateur satisfait une condition. Cest vraiment moche et assez sujet aux erreurs. Dans ces cas, goto
est tout simplement meilleur.
Bien sûr, linstruction étiquetée break
de Java fait de même chose, mais sans vous permettre de sauter à un point arbitraire du code, ce qui résout le problème proprement sans autoriser les choses qui rendent goto
mauvais.
Commentaires
- goto nest jamais une réponse élégante. Lorsque vos boucles sont imbriquées sur plusieurs niveaux, votre problème est que vous navez pas réussi à concevoir votre code pour éviter les boucles multi-incrustées. Les appels de procédure ne sont PAS lennemi. (Lisez les » Lambda: The Ultimate … » papiers.) Utiliser un goto pour sortir de boucles imbriquées plusieurs niveaux profonds, cest mettre un pansement sur une fracture multiple ouverte: cest peut-être simple mais ce nest pas ‘ la bonne réponse.
- Et bien sûr, là nest jamais le cas étrange quand des boucles profondément imbriquées sont nécessaires? Être un bon programmeur nest pas t juste pour suivre les règles, mais aussi pour savoir quand les enfreindre.
- @ JohnR.Strohm Ne dites jamais jamais. Si vous utilisez des termes comme » jamais » en programmation, vous ‘ n’a manifestement pas été traité avec les cas dangle, loptimisation, les contraintes de ressources, etc. Dans les boucles profondément imbriquées, goto est vraiment le moyen le plus propre et le plus élégant de sortir des boucles. ‘ na pas dimportance dans quelle mesure vous ‘ avez refactoré votre code.
- @ JohnR.Strohm: Deuxième plus manqué fonctionnalité lors du passage de VB.NET à C #: la boucle
Do
. Pourquoi? Parce que je peux changer la boucle qui nécessite une rupture profonde dans une boucleDo
et taperExit Do
et là ‘ s aucunGoTo
. Les boucles imbriquées se produisent tout le temps. Rompre les piles se produit quelques% du temps. - @ JohnR.Strohm La seule raison pour laquelle vous dites » goto nest jamais une réponse élégante » parce que vous avez décidé que goto nest jamais une réponse élégante, et par conséquent, toute solution utilisant goto ne peut pas être une réponse élégante.
Réponse
La plupart du découragement vient dune sorte de « religion » qui a été créée autour de Dieu Djikstra et qui était convaincante au début des années 60 à propos de son pouvoir aveugle de :
- sauter nimporte où dans nimporte quel bloc de code
- fonction non exécutée depuis le début
- boucles non exécutées depuis le début
- initialisation de variable ignorée
- sauter de nimporte quel bloc de code sans aucun nettoyage possible.
Cela na plus rien à voir avec le goto
déclaration des langues modernes, dont lexistence est simplement due au support du cr goto
en particulier le premier point principal ci-dessus nest plus autorisé et le second est nettoyé (si vous goto
un bloc la pile est déroulée correctement et tous les destructeurs appropriés sont appelés)
Vous pouvez vous référer à cette réponse pour avoir une idée de la façon dont même ne pas coder lutilisation de goto peut être illisible. Le problème ne vient pas de lui-même, mais de sa mauvaise utilisation.
Je peux écrire un programme entier sans utiliser if
, juste for
. Bien sûr, il ne sera pas bien lisible, un look maladroit et inutilement compliqué.
Mais le problème nest pas for
. Cest moi.
Des choses comme break
, continue
, throw
, bool needed=true; while(needed) {...}
, etc. notent plus que mascarade goto
pour échapper aux cimeterres des fanatiques djikstrariens, que – 50 ans après linvention des langues modernes – veulent toujours leurs prisonniers. Ils ont oublié de quoi parlait Djikstra, ils ne se souviennent que du titre de sa note (GOTO considéré comme nuisible, et ce nétait même pas son titre: il a été changé par léditeur) et blâmer et bash, bash et blâmer chaque produit ayant ces 4 lettre placée en séquence.
Nous sommes en 2011: il est temps de comprendre que goto
a noté pour traiter le GOTO
déclaration que Djikstra était convaincante.
Commentaires
- » Des choses comme pause, continuer , lancer, booléen nécessaire = vrai; tandis que (nécessaire) {…}, etc. ne font pas plus que mascarade goto » Je ne ‘ pas daccord avec cela. Je préférerais que » des choses comme break, etc. soient restreintes goto « , ou quelque chose comme ça. Le principal problème avec goto est quil est généralement trop puissant. Dans la mesure où le goto actuel est moins puissant que celui de Dijkstra ‘, votre réponse me convient.
- @MuhammadAlkarouri: Je suis totalement daccord. Vous venez de trouver une meilleure formulation pour exprimer exactement mon concept. Ce que je veux dire, cest que ces restrictions peuvent parfois ne pas être applicables et que le type de restriction dont vous avez besoin nest pas dans la langue. Ensuite, une chose plus » puissante « , moins spécialisée, est ce qui vous permet de contourner le problème. Par exemple, Java
break n
nest pas disponible en C ++, doncgoto escape
, même siescape
nest pas obligé dêtre juste sorti de la boucle n-ple.
Answer
Létrange va ici ou là, tant quelle est locale à une fonction, nuit rarement à la lisibilité. Elle en profite souvent en attirant lattention sur le fait quil se passe quelque chose dinhabituel dans ce code qui nécessite lutilisation dune structure de contrôle quelque peu inhabituelle .
Si les gotos (locaux) nuisent significativement à la lisibilité, alors cest généralement le signe que la fonction contenant le goto est devenue trop complexe.
Le dernier goto que jai mis dans un morceau de code C consistait à construire une paire de boucles imbriquées. Cela ne rentre pas dans la définition normale de «acceptable» à utiliser, mais la fonction a fini par être beaucoup plus petite et plus claire en conséquence. Pour éviter le goto, il aurait fallu une violation particulièrement désordonnée de DRY.
Commentaires
- La réponse à cette question est la plus lapidement énoncée dans lancien » Lay ‘ s Chips de pommes de terre » slogan: » Je parie que vous ne pouvez ‘ manger quun seul « . Dans votre exemple, vous avez deux » imbriqués » (quoi que cela signifie, et je ‘ Je parie que ce nest pas ‘ t jolie) boucles, et le goto vous a donné un bon marché. Quen est-il du responsable de la maintenance, qui doit modifier ce code après avoir été heurté par un bus? Le goto va-t-il lui rendre la vie plus facile ou plus difficile? Ces deux boucles doivent-elles être repensées?
Réponse
Je pense que tout ce problème a été un cas daboiements le mauvais arbre.
GOTO en tant que tel ne me semble pas problématique, mais plutôt cest très souvent le symptôme dun vrai péché: le code spaghetti.
Si le GOTO provoque Traversée majeure des lignes de contrôle de flux, alors cest mauvais, point final. Si elle ne traverse aucune ligne de contrôle de flux, elle est inoffensive. Dans la zone grise entre les deux, nous avons des choses comme les renflouements de boucle, il y a encore des langages qui nont pas ajouté de constructions qui couvrent tous les cas gris légitimes.
Le seul cas où je me suis retrouvé en train de lutiliser dans de nombreuses années, cest le cas de la boucle où le point de décision est au milieu de la boucle. Il vous reste soit du code dupliqué, soit un drapeau ou un GOTO. Je trouve la solution GOTO la meilleure des trois. Il ny a pas de croisement de lignes de contrôle de flux ici, cest inoffensif.
Commentaires
- Le cas auquel vous faites allusion est parfois appelé « boucle et demie » ou « N plus une demi-boucle » et cest un cas dutilisation célèbre pour
goto
s qui sautent dans une boucle (si le langage le permet; puisque lautre cas, sauter hors de la boucle au milieu, est généralement trivial sansgoto
). - (Hélas, la plupart des langues interdisent de sauter dans une boucle.)
- @KonradRudolph: Si vous implémentez la boucle » » avec GOTO, il ny a pas dautre structure de boucle dans laquelle sauter.
- Je pense que
goto
crie LE FLUX DE CONTRÔLE ICI DOESN ‘ T FIT NORMAL STRUCTURED-PROGRAMMING MOTIFS . Parce que les flux de contrôle qui correspondent à des modèles de programmation structurés sont plus faciles à raisonner que ceux sur lesquels ‘ t, on devrait essayer dutiliser de tels modèles lorsque cela est possible; si le code correspond à de tels modèles, il ne faut ‘ t crier quil ne ‘ t. Dun autre côté, dans les cas où le code ne correspond vraiment pas ‘ à ces modèles, crier à ce sujet peut être mieux que de prétendre que le code correspond alors quil ne correspond pas vraiment ‘ t. - @supercat Eh bien, imaginez que vous avez vous-même écrit un programme, puis le vent le souffle de vos mains. Selon votre logique, vous ne devriez pas ‘ le récupérer, car courir après votre emploi du temps n’était ‘ pas dans votre programme.
Réponse
Oui, le goto peut être utilisé au profit de lexpérience du développeur: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
Cependant, comme pour tout outil puissant (pointeurs, héritage multiple, etc.), il faut être discipliné En lutilisant. Lexemple fourni dans le lien utilise PHP, qui restreint lutilisation de la construction goto à la même fonction / méthode et désactive la possibilité de sauter dans un nouveau bloc de contrôle (par exemple, boucle, instruction switch, etc.)
Réponse
Dépend de la langue. Il est encore largement utilisé dans la programmation Cobol, par exemple. Jai également travaillé sur un appareil Barionet 50, dont le langage de programmation du micrologiciel est un des premiers dialectes BASIC qui, bien sûr, vous oblige à utiliser Goto.
Answer
goto
peut être utile lors du portage du code assembleur hérité vers C. Dans la première instance, une instruction- la conversion par instruction en C, en utilisant goto
en remplacement de linstruction assembleur « s branch
, peut permettre un portage très rapide.
Commentaires
- Correct, mais lun des arguments contre les
goto
est quils déjouent les optimisations du compilateur. - @Sapphire_Brick: De nombreuses optimisations du compilateur sont conçues autour de certains modèles dexécution. Si la tâche à effectuer ne ‘ ne correspond pas aux modèles dexécution pris en charge, » empêcher les optimisations » ne peut pas être une mauvaise chose.
Réponse
Je dirais que non. Ils doivent toujours être remplacés par un outil plus spécifique au problème que goto est utilisé pour résoudre (à moins quil ne soit pas disponible dans votre langue). Par exemple, les instructions break et les exceptions résolvent des problèmes précédemment résolus déchappements de boucle et gestion des erreurs.
Commentaires
- Je ‘ je soutiens que lorsque les langues ont les deux ces fonctionnalités,
goto
est généralement absente de ces langues. - Mais est-ce parce quelles ne sont pas ‘ Vous nen avez pas besoin, ou parce que les gens pensent quils nen ont ‘ pas besoin deux?
- Vos opinions sont sectaires. Il existe de nombreux cas où
goto
est ce qui se rapproche le plus de la sémantique du domaine problématique, tout le reste serait un sale hack. - @ SK-logic: I don ‘ Je ne pense pas que le mot » bigot » signifie ce que vous pensez que cela signifie.
- @Keith,
dévoué de manière intolérante à ses propres opinions et préjugés » – que ‘ est ce que je observer systématiquement ici, avec ce lot de goto-bashing les yeux bandés. » Doit toujours être remplacé » sont fanatiques ‘ s des mots, au moins. Rien de comparable à une opinion correcte et solide, mais juste un fanatisme pur. Cette » toujours » ne laisse aucun espace pour une autre opinion, voyez?
Réponse
Je dirais non. Si vous trouvez la nécessité dutiliser GOTO, je parie quil est nécessaire de repenser le code.
Commentaires
- Peut-être, mais vous ‘ t na fourni aucun raisonnement
- Dijkstra a fourni le raisonnement, en détail, il y a des décennies.
- Just Dogma. Pas de résons. Remarque: Djikstra NEST PLUS UNE RESON VALIDE: il faisait référence à linstruction BASIC ou FORTRAN GOTO des premières années ‘ 60. Ils nont rien à voir avec les gots-s vraiment anémiques (comparés à la puissance de ces) daujourdhui.
- @EmilioGaravaglia Eh bien, la partie de son raisonnement qui sapplique encore aujourdhui est quil ‘ est très facile décrire du code spaghetti en utilisant de nombreux gotos. Cependant, selon cette logique, nous ne devrions ‘ pas utiliser des pointeurs car utiliser autant de pointeurs que
number of gotos needed to create problems
créerait un chaos similaire.
goto
est ce que le processeur fait en fin de compte, mais cela ne fonctionne pas bien avec ce que les humains ont besoin de comprendre et dabstraire car il ny a pas de marque sur la cible finir. Comparez avec IntercalCOMEFROM
.goto
nest pas obligatoire. Cest juste la manière la plus rationnelle de les implémenter dans les langages impératifs, car cest la chose la plus proche de la sémantique même de la transition détat. Et sa destination peut être assez éloignée de la source, elle n’entravera ‘ pas la lisibilité. Mon exemple préféré dun tel code est D.E. Implémentation par Knuth ‘ du jeu Aventure.