if (*this != value) vs. if (this != &value)



  • Hi, schreibt man im operator= eigentlich

    if (*this != value)
    

    oder

    if (this != &value)
    

    ? Ersteres vergleicht wenn ich das richtig sehe die Objekte miteinander sofern der == bzw. != operator vorhanden ist und letzteres schaut ob die Adresse der Objekte identisch ist?

    MyClass& MyClass::operator=(const MyClass& value)
    {
    	if (*this != value)
    	{
            ...
    	}
    	return *this;
    }
    


  • Weder noch.

    T& operator = (T other)
    {
        swap(other);
        return *this;
    }
    

  • Mod

    Das nennt man übrigens Copy & Swap Idiom, wenn du das googlen möchtest. 314159265358979s Code ist eine sehr elegante Schreibweise dafür. Die Kopie wird durch die Übergabe des Funktionsparameters "by value" erzeugt, das swap ist dann eine passende Memberfunktion, welche die kritischen (und die unkritischen, aber ohne kritische Ressourcen brauchst du den Operator gar nicht selber zu schreiben) Ressourcen richtig vertauscht. Bei Verlassen der Funktion werden die Ressourcen der Kopie (also die alten Ressourcen wegen dem vorherigen Swap) zerstört. Selbstzuweisung ist kein Problem, da ja nur eine Kopie zerstört wird. Und Exceptionsicher ist es auch noch. Das ist sogar der Hauptzweck des Idioms.



  • Selbstzuweisung ist hier sehr wohl ein Problem — performance..

    Don't pessimize prematurely

    😉


  • Mod

    Du möchtest bei jeder Zuweisung immer und überall eine Zusatzabfrage einbauen, damit du im Sonderfall, der eigentlich gar nicht vorkommen sollte, dir eine Kopie sparen kannst?



  • SeppJ schrieb:

    Du möchtest bei jeder Zuweisung immer und überall eine Zusatzabfrage einbauen, damit du im Sonderfall, der eigentlich gar nicht vorkommen sollte, dir eine Kopie sparen kannst?

    Da ist ja statistisch gesehen die Performance mehr am Leiden, da es mehr kostet 3000 mal unnötig zu prüfen als einmal eine Kopie ein paar Skalarer Datentypen durchzuführen. cmon.



  • Ich denke, das muss man etwas differenzierter sehen. Wenn Kopien teuer sind, kann eine solche Sonderfallabfrage Zeit sparen - etwa wenn das Objekt eine gut gefüllte std::map enthält. Der Standpunkt, dass Selbstzuweisungen nie vorkommen sollten, scheint mir etwas gewagt -- sicher schreibt niemand

    a = a;
    

    , aber

    *p = *q;
    

    kann schon mal passieren, auch wenn p und q auf das selbe Objekt zeigen. Es ist ja auch nicht so, dass eine Abfrage die Welt kostet - obwohl wenn ich mir manchmal eine portable Variante von gccs __builtin_expect wünsche.

    Was man auch nicht unterschlagen sollte: das Copy&Swap-Idiom ist performancetechnisch dann eine gute Sache, wenn Swaps billig zu haben sind, sonst aber recht teuer. Wenn man seine Datentypen generell verpimplt, mag das trivial erscheinen, aber ich habe auch schon Typen gebaut, die ein paar Kilobyte lokal vorliegen hatten.



  • Ich habe noch nie in einem Code irgendwo eine sinnvolle Situation gehabt wo es zu einer Selbstzuweisung kommen kann.



  • Kann ich nur bestätigen. *q = *p scheint mir nicht wirklich plausibel. Normalerweise macht man eine Zuweisung ja aus (sehr) gutem Grund, und nicht einfach wild in der Gegend. Insofern.. ich glaube nicht, dass ich bei mir schon mal irgendwo eine Selbstzuweisung hatte. (Dass man swap nur bevorzugen sollte wenn das auch billig ist, ist natürlich weiter richtig. Und dann (this == &rhs) natürlich, nur weil zwei Objekte einen Wert haben, sind sie ja nicht das selbe Objekt.)


Anmelden zum Antworten