swap fuer eigene Klasse definieren



  • is ja daemlich 😕



  • Swap ist doch ein Dreizeiler. Wozu der Aufwand? Und brauchen tut man es auch extrem selten.



  • ääää??? schrieb:

    Swap ist doch ein Dreizeiler. Wozu der Aufwand? Und brauchen tut man es auch extrem selten.

    Tja, swap ist eben nicht ein dreizeiler 😉
    swap ist eine der essentiellsten Funktionen die eine Klasse in C++ bieten muss.



  • Shade Of Mine schrieb:

    ääää??? schrieb:

    Swap ist doch ein Dreizeiler. Wozu der Aufwand? Und brauchen tut man es auch extrem selten.

    Tja, swap ist eben nicht ein dreizeiler 😉

    Wann nicht?

    swap ist eine der essentiellsten Funktionen die eine Klasse in C++ bieten muss.

    Wozu?


  • Mod

    ääää??? schrieb:

    Shade Of Mine schrieb:

    ääää??? schrieb:

    Swap ist doch ein Dreizeiler. Wozu der Aufwand? Und brauchen tut man es auch extrem selten.

    Tja, swap ist eben nicht ein dreizeiler 😉

    Wann nicht?

    Weil es keinen logischen Grund gibt, weshalb swap fehlschlagen können sollte. Ein simpler Dreieckstausch dagegen kann ggf. beim Kopieren fehlschlagen - weil unser Objekt irgendwelche Resourcen hält, die erschöpft sind. Zudem kann swap für Klassen sinnvoll sein, die an sich nicht kopierbar sind.

    ääää??? schrieb:

    swap ist eine der essentiellsten Funktionen die eine Klasse in C++ bieten muss.

    Wozu?

    Weil es ein fundamentaler Baustein ist, um exceptionsicheren Code zu schreiben - sofern swap eben selbst keine Exceptions auslösen kann.

    Kleine Anmerkung: Die Bedeutung von swap dürft im neuen Standard zurückgehen, weil es heute häufig gebraucht wird, wenn eigentlich ein move angebracht wäre. Zudem ist ein Dreieckstausch per move statt copy unter den gleichen Randbedingungen unproblematisch.



  • camper schrieb:

    Ein simpler Dreieckstausch dagegen kann ggf. beim Kopieren fehlschlagen - weil unser Objekt irgendwelche Resourcen hält, die erschöpft sind.

    Jetzt wird es interessant. Wie tauscht du den etwas ohne eine Kopie zu machen?



  • ääää??? schrieb:

    camper schrieb:

    Ein simpler Dreieckstausch dagegen kann ggf. beim Kopieren fehlschlagen - weil unser Objekt irgendwelche Resourcen hält, die erschöpft sind.

    Jetzt wird es interessant. Wie tauscht du den etwas ohne eine Kopie zu machen?

    z.B. Zwei Listen, hier genügt es die internen Zeiger zu vertauschen (und geringfügig andere Member wie die Größe). Bei einem Dreickstausch würden zuerst alle Elemente einer Liste in eine temporäre Liste kopiert, dann die Elemente der zweiten Liste in die Erste, dann die Elemente der temporären Liste in die zweite Liste. Der Performanceunterschied sollte erheblich sein.



  • Don06 schrieb:

    z.B. Zwei Listen, hier genügt es die internen Zeiger zu vertauschen (und geringfügig andere Member wie die Größe). Bei einem Dreickstausch würden zuerst alle Elemente einer Liste in eine temporäre Liste kopiert, dann die Elemente der zweiten Liste in die Erste, dann die Elemente der temporären Liste in die zweite Liste. Der Performanceunterschied sollte erheblich sein.

    viel interessanter als die performance ist aber die garantie dass ein swap nicht fehlschlagen kann.

    copy&swap ermoeglicht es transaktionen zu implementieren. man erstellt erst ein temporaeres objekt das alle eigenschaften hat die man haben will und erst wenn das alles erfolgreich war, dann nimmt man das originale objekt und macht ein swap.

    die move semantik mit c++0x wird das ersetzen, da man dann kein swap macht, sondern ein move des temporaeren objektes in das originale macht.

    ohne so eine swap oder move semantik sind sachen wie transaktionen oder funktionen nachd er strong exception guarantee nicht moeglich.

    dass die performance enorm nett ist, ist ein nebeneffekt den man gerne mit nimmt, aber es ist nicht der hauptgrund warum swap so essentiell ist.



  • Don06 schrieb:

    ääää??? schrieb:

    camper schrieb:

    Ein simpler Dreieckstausch dagegen kann ggf. beim Kopieren fehlschlagen - weil unser Objekt irgendwelche Resourcen hält, die erschöpft sind.

    Jetzt wird es interessant. Wie tauscht du den etwas ohne eine Kopie zu machen?

    z.B. Zwei Listen, hier genügt es die internen Zeiger zu vertauschen (und geringfügig andere Member wie die Größe). Bei einem Dreickstausch würden zuerst alle Elemente einer Liste in eine temporäre Liste kopiert, dann die Elemente der zweiten Liste in die Erste, dann die Elemente der temporären Liste in die zweite Liste. Der Performanceunterschied sollte erheblich sein.

    OK, sollte was bringen, aber die Zeiger musst du trotzdem mit nem Dreickstausch tauschen.

    Aber wann braucht ihr den swap so oft? Beim sortieren braucht mans, was aber ja schon meistens fertig implementiertist. Ich kann mich an kaum was errinnern wo ich ein swap gebraucht hab.



  • ääää??? schrieb:

    OK, sollte was bringen, aber die Zeiger musst du trotzdem mit nem Dreickstausch tauschen.

    aber zeiger tauschen kostet nix und kann nicht fehlschlagen.

    Aber wann braucht ihr den swap so oft? Beim sortieren braucht mans, was aber ja schon meistens fertig implementiertist. Ich kann mich an kaum was errinnern wo ich ein swap gebraucht hab.

    zB um einen op= zu implementieren:

    Class& operator=(Class const& other) {
      Class temp(other);
      swap(*this, temp);
      return *this;
    }
    

    Es gibt enorm viele situationen wo man swapen (oder besser gesagt moven) will. immer dann wenn eine operation fehlschlagen kann ist ein swap/move gold wert.

    mit copy&swap hat man eben transaktionen. das swap ist hier das commit.
    und wenn ich ein rollback will, mache ich das swap einfach nicht.


  • Mod

    ääää??? schrieb:

    OK, sollte was bringen, aber die Zeiger musst du trotzdem mit nem Dreickstausch tauschen.

    Schon, aber das war gar nicht Gegenstand meiner Betrachtungen. Getauscht werden soll das ganze Objekt, und dies geschieht nicht durch Dreieckstausch (also Kopieren+2*Zuweisen des ganzen Objektes).

    Kleines Beispiel, wo std::swap sogar mal fehlschlägt und eine eigene Version zwingend erforderlich für diese Funtionalität ist:

    class Container
    {
        class Proxy { ... };
        Proxy operator[](..);
    };
    
    void f()
    {
        Container foo( ... );
        std::swap(foo[0],foo[1]); // tut praktisch das Falsche - und ist formal undefiniert, da Kopieren und Zuweisen bei Proxies fundamental voneinander abweichen
    }
    

Anmelden zum Antworten