Goto?


  • Mod

    volkard schrieb:

    Arcoth schrieb:

    Oder vielleicht noch besser return.

    Nein, das ist eine furchtbare Idee. Immer break . Ich bin mir hundert prozentig sicher dass mir volkard hier zustimmt.

    100% falsch!
    In C++ ist return viel viel toller als break.

    Was!?

    Du willst mir erzählen,

    void foo()
    {
        Schleife
            If DasundDas
                return;
    }
    

    Ist besser als

    void foo()
    {
        Schleife
            If DasundDas
                break;
    }
    

    ? Das ist nämlich was ich meine.



  • Arcoth schrieb:

    Was!?

    Break und return haben eine ganz andere Bedeutung. return heißt, dass die Aufgabe hier abgeschlossen ist und die Funktion den Wert (kann auch void sein) zurückgibt.
    break hingegen ist nichts anderes als ein eingeschränktes goto. Meistens braucht man es in C als zusätzliche Abbruchbedingung, wenn man z.B. etwas sucht. In C++ hat man dank templates aber high-order-functions und kann mit find_if, equals, any_of oder eigenen Funktionen arbeiten, die intern mit return beenden.
    Ich verwende break eigentlich nur dann, wenn sich der Aufwand für einen iterator nicht lohnt oder ich fremden Code einbauen muss.


  • Mod

    Break und return haben eine ganz andere Bedeutung. return heißt, dass die Aufgabe hier abgeschlossen ist und die Funktion den Wert (kann auch void sein) zurückgibt.

    Na genau das meine ich doch! Warum soll return hier pauschal besser sein (nach SG1' Zitat)? Um Schleifen abzubrechen nimmt man break. Auch wenn danach die Prozedur beendet ist.



  • Wie schon geschrieben hilft ein break bei doppelten Schleifen nicht - dann lieber kurze Funktionen und ein return verwenden.
    Häufig will man ja dann auch unterschiedliche Rückgabewerte haben (z.B. true oder false oder bei einer Suchschleife den gefunden Wert bzw. einen Defaultwert) - auch wenn man solche Schleifen wohl gegen eine Algorithmus-Funktion austauschen sollte.



  • zum Entkommen aus mehrfach geschachtelten Schleifen kann man die betreffenden Lauf-Variablen so setzen, daß die Schleifenbedingung nicht mehr erfüllt ist. Also bspw

    i = foo; j = bar;

    zum Entkommen aus dem Inneren von

    for(i = 0; i < foo; ++i){ for(j = 0; j < bar; ++j){ ... } }

    Ob das schön ist, sei mal dahingestellt 🙂



  • Arcoth schrieb:

    Break und return haben eine ganz andere Bedeutung. return heißt, dass die Aufgabe hier abgeschlossen ist und die Funktion den Wert (kann auch void sein) zurückgibt.

    Na genau das meine ich doch! Warum soll return hier pauschal besser sein (nach SG1' Zitat)? Um Schleifen abzubrechen nimmt man break. Auch wenn danach die Prozedur beendet ist.

    Richtig. Man nimmt das, was man ausdrücken möchte.

    Nur würde ich sagen dass man, in einem Fall wo man wirklich 1:1 return gegen break austauschen kann, normalerweise auch "Funktion fertig" ausdrücken möchte und nicht "Schleife fertig".
    Weil das return dabei normalerweise innerhalb eines if steht, dessen Bedingung dem "fertig sein mit der Funktion" entspricht.

    ps: Meist hat man sowieso auch noch Returnwerte. Und in dem Fall finde ich break sowieso furchtbar, weil sehr umständlich.
    Vergleiche

    int FindFooIndex(int foo)
    {
        int index = -1; // Not found
        for (...)
        {
            if (...)
            {
                index = ...;
                break;
            }
        }
        return index;
    }
    
    // vs.
    
    int FindFooIndex(int foo)
    {
        for (...)
            if (...)
                return ...;
    
        return -1; // Not found
    }
    

    Oder gar

    int GetFooBar(int foo)
    {
        bool found = false;
        int bar;
        for (...)
        {
            if (...)
            {
                bar = ...;
                found = true;
                break; // Könnte man in diesem Beispiel auch als "&& !found" in die Laufbedingung verschieben
            }
        }
        if (found)
            return bar;
        else
            throw ...;
    }
    
    // vs.
    
    int GetFooBar(int foo)
    {
        for (...)
            if (...)
                return ...;
    
        throw ...;
    }
    


  • großbuchstaben schrieb:

    zum Entkommen aus mehrfach geschachtelten Schleifen kann man die betreffenden Lauf-Variablen so setzen, daß die Schleifenbedingung nicht mehr erfüllt ist.

    Brr. So einen Hirnfick wie Laufvariablen verändern, nur um ein Goto zu vermeiden? Ich dachte der Grund für die Ablehnung von Goto läge in dessen Potenzial, zum Schreiben schwer nachvollziehbaren Codes verwendet zu werden. Ein "goto out" ist aber doch erfrischend klar, verglichen mit künstlichen Flags oder gar Rumgefummel an den Schleifenzählern.



  • @goto *(&&label +
    Bin grundsätzlich ganz deiner Meinung.

    Bis auf das kleine Detail, dass ich in den letzten 5~10 Jahren weder goto noch goto -Umgehung durch Verändern von Laufvariablen gebraucht habe.
    (Und natürlich auch sonst keine schmutzigen Tricks wie Exceptions zu werfen o.ä.)

    Alle Fälle wo man das eine oder andere zu brauchen meinen könnte, haben sich anders (mMn. "schöner"/"eleganter") lösen lassen. Meist durch das Rausziehen der verschachtelten Schleifen in eine eigene Funktion, so dass man dann return als "multi break" verwenden kann.
    Manchmal auch durch das "Zerteilen" der verschachtelten Schleifen in mehrere Funktionen die dann jeweils nur mehr eine der Schleifen enthalten.



  • volkard schrieb:

    In C++ ist return viel viel toller als break.

    Einwand: return verlässt sofort die aktuelle Funktion. Man kann bei verschachtelten Schleifen dann in der Funktion nicht fortfahren. Vielleicht doch besser mit break.

    Hier ein Beispiel in C# (düfte in C++ geringfügig anders aussehen)

    private void Form1_Load(object sender, EventArgs e)
      {
          int  i=0, j=0, k=0;
          bool exit = false;
    
          for (i = 0; i < 50; i++)
          {
              if (exit) break;
              for (j = 0; j < 50; j++)
              {
                   if (exit) break;
                   for (k = 0; k < 50; k++)
                   {
                   // Abbruch einer verschachtelten Schleife
                      if ((i==6) & (j==3) & (k == 10))
                      {
                          exit = true;
                          i--;
                          j--;
                          break;
                          //return;
                      }
                   }
               }
          }
          // mit return kommt man hier überhaupt nicht hin!
          // mit break kann man hier aber nach dem Abbruch weiterarbeiten!
          MessageBox.Show("exit    " + exit.ToString() +    // TRUE
                          "\ni         " + i.ToString() +   // 6
                          "\nj         " + j.ToString() +   // 3
                          "\nk         " + k.ToString());   // 10 
       }
    

    Geht doch allein mit break! 🕶 GOTO ist in jedem Fall mega out! 😡



  • Geht auch gut mit return

    void xXx::Form1_Load(object & sender, EventArgs & e)
    {
    	int  i=0, j=0, k=0;
    
    	auto lmbd = [&]()
    	{
    		for (i = 0; i < 50; i++)
    		{
    			for (j = 0; j < 50; j++)
    			{
    
    				for (k = 0; k < 50; k++)
    				{
    					// Abbruch einer verschachtelten Schleife
    					if ((i==6) & (j==3) & (k == 10))
    					{
    						return;
    					}
    				}
    			}
    		}
    	}();
    
    	// mit return kommt man hier sehr gut  hin!
    	// und man kann hier auch nach dem Abbruch weiterarbeiten!
    	MessageBox.Show("exit    " + exit.ToString() +    // TRUE
    	"\ni         " + i.ToString() +   // 6
    	"\nj         " + j.ToString() +   // 3
    	"\nk         " + k.ToString());   // 10
    }
    

    (Wenn man den Code mal dümmlich als C++ ansieht, aber ich denekd as Prinzip sollte klar sein...)

    PS: Das mit dem Break nach dem if, dass da nicht die Zeile umgebrochen ist: Das ist ne Todsünde. Mindestens genauso wie mein return 0x0; 😃
    Trollololol



  • berniebutt schrieb:

    volkard schrieb:

    In C++ ist return viel viel toller als break.

    Einwand: return verlässt sofort die aktuelle Funktion. Man kann bei verschachtelten Schleifen dann in der Funktion nicht fortfahren. Vielleicht doch besser mit break.

    Hier ein Beispiel in C# (düfte in C++ geringfügig anders aussehen)

    Wenn Du die Berechnungen nicht auslagerst, sondern alles in die Button-Handler schmierst, hilft return natürlich wenig.


Anmelden zum Antworten