goto szinte nem ajánlott. Érdemes valaha is használni ezt az állítást?

Megjegyzések

  • xkcd.com/292
  • goto a CPU végső soron ezt teszi, de nem működik jól azzal, amit az embereknek meg kell érteniük és elvonatkoztatniuk, mivel nincs nyom a célponton vége. Hasonlítsa össze az Intercal COMEFROM elemekkel.
  • @Thorbj ø rnRavnAndersen, mit jelentenek még az emberek, amikor ‘ az államgép állapotátmeneteiről beszél? ‘ nem lát hasonlóságot? ” Lépjen egy adott állapotba “, hogy ‘ s amit jelent és bármi más nem lenne más, mint egy ilyen triviális dolog felesleges bonyodalma. És mit értesz ” nincs jelölés ” alatt? A címke ilyen jel.
  • @ SK-logic, attól függ, hogy milyen messzire engedi meg a goto ‘ s származását. Az állami gépek nem igénylik a goto végrehajtását.
  • @Thorbj ø rnRavnAndersen, természetesen goto nem szükséges. Ez csak a legracionálisabb módszer az imperatív nyelveken történő megvalósításra, mivel ez áll a legközelebb az államátmenet szemantikájához. És rendeltetési helye meglehetősen távol állhat a forrástól, nem fogta ‘ akadályozni az olvashatóságot. Kedvenc példám egy ilyen kódra a D.E. Knuth ‘ kalandjáték megvalósítása.

Válasz

Ezt már többször megvitatták a Stack Overflow-n, és Chris Gillum összefoglalta a goto lehetséges felhasználásait:

Tisztán kilép egy funkcióból

Gyakran egy funkcióban kioszthat erőforrásokat, és több helyen kell kilépnie. A programozók leegyszerűsíthetik kódjukat, ha az erőforrás-megtisztító kódot a függvény végére teszik, ha a funkció minden ” kilépési pontja ” a takarítási címkét. Így nem kell megtisztító kódot írni a függvény minden ” kilépési pontjára “.

Beágyazott hurkok kilépése

Ha beágyazott hurokba kerül, és ki kell törnie a minden hurok, egy goto ezt sokkal tisztábbá és egyszerűbbé teheti, mint a break utasítások és az if-ellenőrzések.

Alacsony szintű teljesítménybeli fejlesztések

Ez csak tökéletes kritikus kódban érvényes, de a goto utasítások nagyon gyorsan végrehajtódnak, és lendületet adhatnak, ha egy funkcióban mozog. Ez azonban kétélű kard, mert a fordító általában nem tudja optimalizálni a gotókat tartalmazó kódot.

Én “vitatkoznék, mint sokan mások , hogy ezekben az esetekben a goto használatát arra használják, hogy kijussanak egy sarokból, ahová kódolták magukat, és általában a kód tünete, amelyet visszafejleszteni lehet .

Megjegyzések

  • Az első problémát a finally blokkok modern nyelveken nagyon rendesen megoldják, és a másodikat break s címkével oldja meg. Ha ‘ mégis ragaszkodik a C-hez, goto nagyjából az egyetlen módja e problémák elegáns megoldásának.
  • Nagyon jó pontok. Szeretem, ha a Java lehetővé teszi a hurkok többszintű kitörését
  • @Chinmay – végül csak blokkol vonatkozik 1) a modern nyelvekre, amelyek rendelkeznek velük, és b) tolerálhatja a rezsit (a kivételkezelésnek viszont van rezsije. ) Vagyis a finally használata csak ilyen feltételek mellett érvényes. Nagyon ritka, mégis érvényes helyzetek vannak, ahol a goto a helyes út.
  • Oké, emberek … mi a fene a különbség break 3 vagy break myLabel és goto myLabel. Ó, ‘ csak a kulcsszó helyes. Ha break, continue vagy más hasonló kulcsszót használ, akkor goto (Ha a for, while, foreach, do/loop szolgáltatást használja, feltételes goto-t használ.)
  • Az alacsony szintű teljesítményről – a modern processzor viselkedését nehéz megjósolni (pipeline, megbízáson kívüli végrehajtás), így valószínűleg az esetek 99% -ában nem éri meg, vagy akár lassabb is lehet. @MatthewWhited: Terjedelem. Ha tetszőleges ponton adja meg a hatókört, nem világos (az ember számára), hogy milyen konstruktorokat kell hívni (a probléma C-ben is fennáll).

Válasz

A magasabb szintű vezérlési folyamat konstrukciók általában megfelelnek a problématerület fogalmainak. Az if / else valamilyen feltételen alapuló döntés. Egy hurok azt mondja, hogy bizonyos műveleteket ismételten hajtson végre. Még egy break mondat is azt mondja: “ezt többször csináltuk, de most le kell állnunk”.

Egy goto utasítás viszont hajlamos megfelelni a futó program fogalmának, nem pedig a problémás tartomány. Azt mondja, hogy folytassa a végrehajtást a program meghatározott részében a program ban. Valakinek, aki elolvassa a kódot, ki kell következtetnie , hogy ez mit jelent a problémás tartomány szempontjából.

Természetesen az összes magasabb szintű konstrukció definiálható gotók és egyszerű feltételes elágazások alapján. . Ez nem azt jelenti, hogy pusztán álruhában vannak. Gondoljon rájuk korlátozott gótokra – és ezek a korlátozások teszik hasznossá őket. A break utasítás egy ugrásként valósul meg a záró hurok végéig, de jobb, ha a ciklus egészén működik.

Ha minden más egyenlő, akkor a kód, amelynek szerkezete a problémás tartomány struktúráját tükrözi, általában könnyebben olvasható és karbantartható.

Nincs olyan eset, amikor feltétlenül szükséges egy goto utasítás (erre van egy “s tétel ), de vannak olyan esetek, amikor a legkevésbé rossz megoldás lehet. Ezek az esetek eltérnek nyelvről nyelvre, attól függően, hogy a nyelv milyen magasabb szintű konstrukciókat támogat.

Például a C-ben három alapvető forgatókönyv létezik, ahol a goto megfelelő.

  1. Kitört egy beágyazott hurokból. Ez szükségtelen lenne, ha a nyelvnek lenne egy felcímkézett break utasítása.
  2. Hiba vagy más váratlan esemény esetén egy kódrészlet (általában egy függvénytörzs) kiküszöbölése. . Ez szükségtelen lenne, ha a nyelvnek lenne kivétele.
  3. Egy explicit véges állapotgép megvalósítása. Ebben az esetben (és azt hiszem, csak ebben az esetben) egy goto közvetlenül felel meg a problématerület fogalmának, áttérve egyik állapotról egy meghatározott másik állapotra, ahol az aktuális állapotot az a kódrészlet képviseli, amely éppen fut .

Másrészt egy explicit véges állapotú gép is megvalósítható egy kapcsoló utasítással egy hurokban. Ennek az az előnye, hogy minden állapot ugyanabban a helyen kezdődik a kódban, ami hasznos lehet például a hibakeresésben.

A goto fő használata egy ésszerűen modern nyelven (amely támogatja az if / else and loops) egy vezérlési folyamat konstrukció szimulálása, amely hiányzik a nyelvből.

Megjegyzések

  • Ez eddig a legjobb válasz – meglehetősen meglepő, másfél éves kérdésre. 🙂
  • +1 a ” eddigi legjobb válaszra “. — ” A goto ésszerűen modern nyelvű (az if / else és a ciklusokat támogató) nyelv fő célja egy vezérlési folyamat szimulálása olyan konstrukció, amely ‘ hiányzik a nyelvből. ”
  • A switch-utasítás állapotgépben minden írás a a kontrollérték valóban egy goto. Az SSSM ‘ s gyakran jó struktúrák, mivel kivonatolja az SM állapotot a végrehajtási konstrukcióból, de nem ‘ nem igazán szüntetik meg a ” gotos “.
  • ” Ha minden más egyenlő, akkor a kód, amelynek szerkezete a problémás tartomány struktúráját tükrözi, általában könnyebben olvasható és karbantartható. ” Én ‘ ezt sokáig tudtam, de hiányoztak a szavak, hogy olyan pontosan kommunikálhassák, hogy más a programozók valóban megértik és meg is fogják érteni. Köszönöm ezt.
  • A ” strukturált program tétel ” szórakoztat, mivel hajlamos egyértelműen demonstrálni a rámutat arra, hogy strukturált programozási utasítások használata a goto utánzásához sokkal kevésbé olvasható, mint egyszerűen a goto használata!

Válasz

Bizonyára a programozási nyelvtől függ. A goto ellentmondásos oka elsősorban annak a rossz hatásának köszönhető, amely akkor következik be, amikor a fordító túl szabadon engedi használni. Problémák merülhetnek fel például abban az esetben, ha ez lehetővé teszi a goto használatát oly módon, hogy most már elérheti az inicializálatlan változót, vagy ami még rosszabb, ha másik módszerre ugrik és elrontja a hívást Kazal. A fordító felelőssége az értelmetlen vezérlési folyamat letiltása.

A Java megpróbálta “megoldani” ezt a problémát a goto teljes tiltásával. A Java azonban lehetővé teszi az return használatát egy finally blokk belsejében, és ezáltal a kivétel akaratlanul lenyeli.Ugyanez a probléma továbbra is fennáll: a fordító nem végzi a dolgát. A (z) goto eltávolítása a nyelvből nem javította ki.

A C # mezőben a goto ugyanolyan biztonságos, mint a break, continue, try/catch/finally és return. Nem enged inicializálatlan változókat használni, nem enged kiugrani egy utolsó blokkból stb. A fordító panaszkodni fog. Ez azért van, mert megoldja a valós problémát, ami mintha értelmetlen vezérlési folyamatot mondtam volna. A goto nem vonja vissza varázslatosan a határozott hozzárendelés elemzését és az ésszerű fordítói ellenőrzéseket.

Megjegyzések

  • Az a véleményed, hogy a C # ‘ s goto nem gonosz? Ha igen, akkor ez minden rutinszerűen használt goto konstrukciójú nyelv esetében érvényes, nem csak a C # …

Válasz

Igen. Ha a hurkok több szint mélyen beágyazódnak, a goto az egyetlen módja annak, hogy elegánsan kitörjön egy belső hurokból. A másik lehetőség az, hogy beállítunk egy zászlót, és kitörünk minden hurokból, ha az megfelel egy feltételnek. Ez nagyon csúnya, és meglehetősen hibára hajlamos. Ezekben az esetekben a goto egyszerűen jobb.

Természetesen a Java break feliratú utasítás is ugyanezt teszi dolog, de anélkül, hogy egy tetszőleges pontra ugorna a kódban, amely szépen megoldja a problémát anélkül, hogy megengedné azokat a dolgokat, amelyek goto t gonosszá tesznek. / h3>

  • a goto soha nem elegáns válasz. Ha a hurkok több szint mélyen be vannak ágyazva, akkor az a problémád, hogy nem sikerült a kódodat felépítened a többpróbás ciklusok elkerülése érdekében. Az eljáráshívások NEM az ellenség. (Olvassa el a ” Lambda: A végső … ” papírokat.) A goto segítségével hurkokból való kitörés több beágyazott A szintek mélye egy sávsegéd egy nyílt, többszörös törésre: lehet, hogy egyszerű, de nem ‘ ez a helyes válasz.
  • És természetesen ott Soha nem furcsa eset, amikor mélyen beágyazott hurkokra van szükség? Jó programozónak lenni nem t csak a szabályok betartásáról, hanem arról is, hogy mikor kell megszegni őket.
  • @ JohnR.Strohm Soha ne mondd, hogy soha. Ha olyan kifejezéseket használ, mint ” never ” a programozásban, akkor ‘ egyértelműen nem foglalkozik sarok esetekkel, optimalizálással, erőforrás-korlátokkal stb. A mélyen beágyazott hurkoknál a goto valóban a legtisztább, legelegánsabb módja a ciklusokból való kilépésnek. Nem számít, hogy ‘ nem számít, mennyire ‘ szerkesztette újra a kódját.
  • @ JohnR.Strohm: A második leggyakrabban hiányzott funkció a VB.NET-ről a C # -ra váltáskor: a Do hurok. Miért? Mivel egy mély szakítást igénylő hurkot megváltoztathatok egy Do ciklusra, és beírhatom az Exit Do szöveget, és ott ‘ s nem GoTo. A beágyazott hurkok folyamatosan történnek. A halmok feltörése az esetek bizonyos százalékában történik.
  • @ JohnR.Strohm Az egyetlen ok, amiért azt mondod, hogy ” goto, soha nem elegáns válasz ” azért van, mert arra gondolt, hogy a goto soha nem elegáns válasz, ezért a goto használatával végrehajtott bármely megoldás nem lehet elegáns válasz.

Válasz

A csüggedés legnagyobb része egyfajta “vallásból” származik, amelyet Isten Djikstra nagy Isten teremtett, és amely a 60-as évek elején kénytelen volt válogatni :

  • bárhová ugorhat bármelyik kódblokkba
    • a kezdetektől nem végrehajtott funkció
    • az elejétől nem végrehajtott ciklusok
    • kihagyta a változó inicializálását
  • ugorjon el bármilyen kódtömbtől minden lehetséges tisztítás nélkül.

Ennek semmi köze a goto állítása a modern nyelveknek, amelyek létezése pusztán a cr támogatásának köszönhető a megadott nyelvtől eltérő kódstruktúrák megadása.

Különösen a fenti első fő pont már megengedett, a második pedig megtisztul (ha goto egy blokkot a verem megfelelően kikapcsolja és az összes megfelelő rombolót meghívja)

A erre a válaszra hivatkozhat, hogy képet alkothasson arról, hogy a páros kód miért nem a goto használata olvashatatlan lehet. A probléma nem maga a goto, hanem a helytelen használata.

Egy teljes programot írhatok a if használata nélkül, csak for. Természetesen nem lesz jól olvasható, ügyetlen és feleslegesen bonyolult megjelenés.

De a probléma nem for. Én vagyok.

Ilyenek például: break, continue, throw, bool needed=true; while(needed) {...} stb. több mint álarcot goto jeleznek, hogy elkerüljék a dzsikstrári zellóták scimitareit, hogy – 50 évvel a modern laguage feltalálása után – továbbra is akarják a foglyaikat. Elfelejtették, miről beszélt Djikstra, csak a jegyzet címére emlékeztek (a GOTO károsnak tartotta, és nem is az ő saját címe volt: a szerkesztő megváltoztatta), és hibáztattak, bash, bash és hibáztattak minden olyan cselekményt, amelynek ez a 4 sorrendben elhelyezett levél.

2011: itt az ideje megérteni, hogy goto nem kell foglalkoznia a GOTO nyilatkozat, amellyel Djikstra meggyőző volt.

Megjegyzések

  • ” Ilyenek például a szünet, folytatás , dobás, bool szükséges = igaz; míg (szükséges) {…} stb. többet jegyeznek, mint álarcos goto “, nem értek egyet ‘. Inkább a ” dolgokat részesíteném előnyben, például a szünet stb. korlátozott goto “, vagy ilyesmi. A goto fő problémája, hogy általában túl erős. Amennyiben a jelenlegi goto kevésbé erőteljes, mint Dijkstra ‘ s, a válaszod jó velem.
  • @MuhammadAlkarouri: Teljesen egyetértek. Most találtál egy jobb megfogalmazást, hogy pontosan kifejezzem a koncepciómat. Azt akarom mondani, hogy ezek a korlátozások néha nem alkalmazhatók, és az Ön számára szükséges korlátozások nem a nyelven állnak rendelkezésre. Akkor egy ” erőteljesebb, kevésbé specializált ” dolog az, ami képes megkerülni. Például a Java break n nem érhető el C ++ nyelven, ezért goto escape, még akkor is, ha escape nem szükséges, hogy csak az n-ple hurkon legyen.

Válasz

A páratlan itt vagy ott, mindaddig, amíg lokalizálódik egy függvény számára, ritkán károsítja jelentősen az olvashatóságot. Gyakran előnyös számára, ha felhívja a figyelmet arra, hogy ebben a kódban valami szokatlan történik, ami egy kissé szokatlan vezérlő struktúra használatát igényli .

Ha a (helyi) gotók jelentősen károsítják az olvashatóságot, akkor ez általában annak a jele, hogy a goto-t tartalmazó funkció túl bonyolulttá vált.

Az utolsó goto, amelyet egy A C kód darabja egy összekapcsolt hurok párjának felépítése volt. Ez nem illeszkedik az “elfogadható” goto használat szokásos definíciójába, de ennek eredményeként a funkció lényegesen kisebb és tisztább lett. A goto elkerülése érdekében a DRY különösen zűrzavaros megsértésére lett volna szükség.

Megjegyzések

  • Erre a válasz a legdurvább módon a régi ” Lay ‘ s burgonya chips ” szlogen: ” Fogadhat, hogy ‘ nem ehet csak egyet “. Példádban két ” reteszelő ” van (bármit is jelent ez, és I ‘ m fogadások nem ‘ t eléggé) hurkok, és a goto olcsóbb eredményt adott. Mi a helyzet a karbantartó sráccal, akinek módosítania kell ezt a kódot, miután elütött egy busz? A goto megkönnyíti vagy megnehezíti az életét? Szüksége van ennek a két ciklusnak az újragondolására?

Válasz

Úgy gondolom, hogy ez az egész kérdés ugatás volt. a rossz fa.

A GOTO mint olyan nem tűnik problémásnak számomra, sokkal inkább a tényleges bűn tünete: spagettikód.

Ha a GOTO okozza az áramlásszabályozó vonalak nagyobb átkelése, akkor ez rossz időszak. Ha nem keresztez áramlásszabályozó vezetékeket, akkor ártalmatlan. A köztük lévő szürke zónában vannak olyan dolgok, mint a hurokmentés, még mindig vannak olyan nyelvek, amelyek nem adtak hozzá olyan konstrukciókat, amelyek lefednék az összes legitim szürke esetet.

Az egyetlen eset, amikor azt tapasztaltam, hogy ténylegesen használom sok évben a hurok esete, amikor a döntési pont a hurok közepén van. Vagy lemásolt kóddal, zászlóval vagy GOTO-val marad. A GOTO megoldást találom a három közül a legjobbnak. Itt nincs kereszteződés az áramlásszabályozó vonalakon, ez ártalmatlan.

Megjegyzések

  • Az Ön által hivatkozott esetet néha „másfél huroknak” vagy „N plusz egy fél huroknak” nevezik, és ez egy híres használati eset a ek (ha a nyelv ezt megengedi; mivel a másik esetben a középső hurokból való kiugrás általában triviális goto nélkül ).
  • (Jaj, a legtöbb nyelv tiltja a hurokba ugrást.)
  • @KonradRudolph: Ha megvalósítja a ” ciklust ” a GOTO-val nincs más hurokszerkezet, ahova be kellene ugrani.
  • Úgy gondolom, hogy goto úgy kiabálok, A VEZÉRLŐFOLYAM ITT NEM ‘ T NORMÁL SZERKEZETES-PROGRAMOZÁS MINTÁK at. Mivel a strukturált programozási mintákhoz illeszkedő vezérlési folyamatokat könnyebb megalapozni, mint azokat, amelyek nem ‘ t használnak, meg kell próbálni ilyen mintákat használni, amikor csak lehetséges; ha a kód megfelel az ilyen mintáknak, nem szabad ‘ t kiabálni, hogy nem ‘ t. Másrészt azokban az esetekben, amikor a kód valóban nem felel meg az ilyen mintáknak, a kiabálás jobb lehet, mintha a kód beillesztése lenne, ha valóban nem felel meg ‘ t.
  • @supercat Nos, képzelje el, hogy írt magának egy ütemtervet, majd a szél kifújja a kezéből. Logikája szerint nem szabad ‘ lekérni, mert az ütemezése után hajszolás nem volt ‘ az ütemezése szerint.

Válasz

Igen, a goto felhasználható a fejlesztő tapasztalatainak javára: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

Azonban ugyanúgy, mint bármely más hatékony eszköznél (mutatók, többszörös öröklés stb.), fegyelmezni kell használni azt. A linkben található példa PHP-t használ, amely korlátozza a goto konstrukció használatát ugyanarra a függvényre / módszerre, és letiltja az új vezérlőblokkba (pl. Ciklus, kapcsoló utasítás stb.) Való ugrás lehetőségét

Válasz

A nyelvtől függ. Még mindig széles körben használják például a Cobol programozásban. Dolgoztam egy Barionet 50 eszközön is, amelynek firmware programozási nyelve egy korai BASIC dialektus, amely természetesen megköveteli a Goto használatát.

Válasz

goto hasznos lehet, ha a régi assembler kódot C-be hordozza. Először egy utasítás- az utasítással történő átalakítás C-ba, az goto használatával az “s branch összeszerelő utasítás helyettesítéseként, lehetővé teszi a nagyon gyors portolást.

Megjegyzések

  • Helyes, de a goto s ellen az egyik érv az, hogy megakadályozzák a fordító optimalizálását.
  • @Sapphire_Brick: Számos fordító optimalizálást terveznek bizonyos végrehajtási minták köré. Ha az elvégzendő feladat nem ‘ nem felel meg a támogatott végrehajtási mintáknak, ” megakadályozhatja az ” optimalizálást legyen rossz dolog.

Válasz

Nemmel érvelnék. Ezeket mindig ki kell cserélni egy olyan eszközzel, amely specifikusabb arra a problémára, amelynek megoldására a goto-t használják (kivéve, ha ez nem érhető el az Ön nyelvén). Például a break utasítások és a kivételek megoldják a hurok megszökésének korábban goto-val megoldott problémáit és hibakezelés.

Megjegyzések

  • I ‘ azt állítom, hogy amikor a nyelvek mindkettő ezek a funkciók, goto általában hiányoznak ezekből a nyelvekből.
  • De azért, mert nem ‘ nincs rájuk szükségük, vagy azért, mert az emberek úgy gondolják, hogy nincsenek ‘ nekik szükségük?
  • A nézeteitek nagybetűsek. Sok esetben fordul elő A goto a legközelebb a problémás tartomány szemantikájához, bármi más piszkos hack lenne.
  • @ SK-logic: Nem ‘ nem gondolja, hogy a ” bigott ” szó azt jelenti, amit ön szerint jelent.
  • @Keith,

intoleránsan odaadó saját véleményének és előítéleteinek ” – hogy ‘ amit én következetesen figyelje meg itt, ezzel a goto-bashing bekötött szemmel. “ mindig ki kell cserélni ” fanatikusak ‘ szavak legalább. Semmi sem megfelelő, megalapozott vélemény, csak egy tiszta fanatika. Ez ” mindig ” nem hagy teret alternatív vélemények számára, lásd?

Válasz

Nemet mondanék. Ha úgy találja, hogy szükség van a GOTO használatára, fogadni fogok arra, hogy újraterveznünk kell a kódot.

Megjegyzések

  • Lehet, de te a haven ‘ nem nyújtott be semmilyen indoklást
  • Dijkstra évtizedekkel ezelőtt részletesen kifejtette az érvelést.
  • Csak a dogma. Nincsenek resonok. Megjegyzés: A Djikstra NEM TÖBB ÉRVÉNYES EREDMÉNY: a korai ‘ 60-as évek BASIC vagy FORTRAN GOTO utasítására hivatkozott. Semmi közük a mai vérszegénységhez (ezek erejéhez képest).
  • @EmilioGaravaglia Nos, érvelésének a mai napig érvényes része az, hogy ‘ nagyon könnyű spagettikódot írni sok gót használatával. E logika szerint azonban nem szabad ‘ használnunk mutatókat, mert ahány mutatót használ, mint number of gotos needed to create problems, hasonló káosz alakulna ki.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük