Operator Überladung ( operator= )



  • Hallo Leute, wollte euch mal um Rat bitten.

    Wollte wissen wie man den operator= am besten überladen kann.
    Habe ein Objekt A der Classe X und ein Objekt B der Classe X, und will das B eine Kopie von A wird. Sollte ich das am besten so machen oder gibt es da einen einen schöneren Weg?

    class X {
    public:
      X(){}
      ~X(){}
      void operator= ( X& a ) {
        memcopy ( this, &a, sizeof ( X ) );
      }
    }
    

    Für mich erscheint das vollkommen banal, aber dennoch irgendwie richtig.

    Gruß Slux



  • Nö. Kopierkonstruktor, Zuweisungsoperator und Destruktor deklariert und implementiert man nicht wirklich so oft. Der Compiler kann diese Dinger auch selbst generieren und "kopiert" dann einfach elementweise (ruft deren Kopier-Operationen auf). Also:

    class X
    {
    };
    

    Das Ding ist immer noch

    • default-konstuierbar
    • kopier-konstruierbar
    • zuweisbar
    • zerstörbar

    Vielleicht wirste mal ein bisschen konkreter, um was es für eine Klasse sich bei dir dreht, was sie für Elemente hat und so weiter ...



  • Also die Klasse an sich ist recht Komplex, beinhaltet Unmengen an verschiedenen Daten, angefangen bei einfachen Variablen bis hin weg zu komplexeren Strukturen. ( dennoch alles im Stack, nicht im Heap )

    Also das das Verfahren mit dem memcpy hab ich als das einfachste gesehen, egal ob bei dem operator= oder ob bei einem Kopier-Konstruktor. Es Funktioniert auch so wie ich es will, aber erscheint mir halt sehr stark C-Like.



  • Slux schrieb:

    Also die Klasse an sich ist recht Komplex, beinhaltet Unmengen an verschiedenen Daten, angefangen bei einfachen Variablen bis hin weg zu komplexeren Strukturen. ( dennoch alles im Stack, nicht im Heap )

    Das hat mit Stack oder Heap nichts zu tun.

    Slux schrieb:

    Also das das Verfahren mit dem memcpy hab ich als das einfachste gesehen, egal ob bei dem operator= oder ob bei einem Kopier-Konstruktor. Es Funktioniert auch so wie ich es will, aber erscheint mir halt sehr stark C-Like.

    Es funktioniert bestimmt nicht bei "komplexeren Strukturen". Weißt du überhaupt was memcpy macht?

    struct Example
    {
    	Example()
    		: p(new char(123))
    	{
    	}
    
    	~Example()
    	{
    		delete p;
    	}
    
    private:
    
    	char *p;
    };
    
    int main()
    {
    	{
    		Example a, b;
    		memcpy(&a, &b, sizeof(a));
    	}
    
    	//das gleiche* wie:
    	{
    		char *pa = new char, *pb = new char; //Konstrukoren
    		pa = pb; //memcpy
    		delete pb; //Destruktor
    		delete pa; //Destruktor
    	}
    
    	//der Speicher, auf den pa ursprünglich zeigte, ist weg (Leck)
    	//der von pb wird doppelt freigegeben, was in C++ nicht erlaubt ist
    }
    
    //* die zweite Variante hat ein Speicherleck, da das zweite [c]new[/c] werfen kann
    

    Die korrekte Variante:

    struct Example
    {
    	Example()
    		: p(new char(123))
    	{
    	}
    
    	~Example()
    	{
    		delete p;
    	}
    
    	Example(const Example &other)
    		: p(new char(*other.p))
    	{
    	}
    
    	Example &operator = (const Example &other)
    	{
    		p = new char(*other.p);
    		return *this;
    	}
    
    private:
    
    	char *p;
    };
    
    int main()
    {
    	Example a, b;
    	a = b;
    
    	//keine Problem
    }
    

    (Das ist nur ein Beispiel. In echtem Code kommt fast nie delete vor, das wäre ganz übler Stil.)

    Diese Art von Kopieroperator ist aber nicht wirklich ausnahmesicher:

    struct Example2
    {
    	Example2()
    		: number(0)
    	{
    	}
    
    	Example2(const Example2 &other)
    		: name(other.name)
    		, plz(other.plz)
    		, number(other.number)
    	{
    	}
    
    	// nicht ausnahmesicher
    	Example2 &operator = (const Example2 &other)
    	{
    		name = other.name;
    		plz = other.plz; //falls das wirft, ist das Objekt nur teilweise kopiert worden
    		number = other.number;
    		return *this;
    	}
    
    	// ausnahmesicher, falls swap es bei allen Membern ist
    	// Nachteil: kann etwas langsamer sein
    	Example2 &operator = (Example2 other)
    	{
    		swap(other);
    		return *this;
    	}
    
    	void swap(Example2 &other)
    	{
    		//swap ist in der Regel so implementiert, dass es nicht wirft
    		std::swap(name, other.name);
    		std::swap(plz, other.plz);
    		std::swap(number, other.number);
    	}
    
    private:
    
    	std::string name;
    	std::string plz;
    	unsigned number;
    };
    

    Die meisten Klassen müssen aber gar nicht kopiert werden. Besonders bei "Ummengen verschiedener Daten" hört sich das nicht gut an. Warum musst du so etwas kopieren? Und vor allem: Warum tun es nicht die automatisch generierten Kopiermethoden?



  • @Slux
    memcpy(this, ...) ist fast immer falsch. C++ erlaubt dir zwar ein Objekt mit memcpy zu überschreiben, nur wird es dabei laut Standard zerstört. Und zwar (natürlich) ohne dass der Destruktor aufgerufen wird.

    Code der Klassen mit memcpy rumkopiert funktioniert zwar (dummerweise) mit den meisten Implementierungen, aber vom Standard abgedeckt ist das nur bei sog. "POD Klassen" (welche Anforderungen eine Klasse genau erfüllen muss damit sie eine "POD Klasse" ist würde den Rahmen hier sprengen, google es einfach wenn es dich interessiert).

    Also am besten einfach nicht machen.

    Slux schrieb:

    Also das das Verfahren mit dem memcpy hab ich als das einfachste gesehen, egal ob bei dem operator= oder ob bei einem Kopier-Konstruktor. Es Funktioniert auch so wie ich es will, aber erscheint mir halt sehr stark C-Like.

    Wenn die memcpy Variante funktioniert, dann solltest du normalerweise den Zuweisungsoperator bzw. Kopierkonstruktor überhaupt nicht selbst definieren müssen (da dir von C++ ein automatisch definierter Kopierkonstruktor und Zuweisungsoperator zur Verfügung gestellt werden, die "das richtige machen").
    Beispiel:

    #include <iostream>
    
    class X
    {
    public:
        X(int x) : m_x(x) {}
        void PrintMe() { std::cout << m_x << std::endl; }
    private:
        int m_x;
    };
    
    int main()
    {
        X a = 23;
        X b = 5;
    
        b.PrintMe(); // 5
        b = a;
        b.PrintMe(); // 23
    
        X c = b;
        c.PrintMe(); // 23
    }
    


  • Danke erst einmal an euch 🙂

    Wusste nicht, dass es einen Standard Kopiermethode gibt. m(

    (Das ist nur ein Beispiel. In echtem Code kommt fast nie delete vor, das wäre ganz übler Stil.)

    Wieso sollte kein delete vorkommen? Wie soll ich denn alles löschen, was ich via new erstellt habe?



  • Slux schrieb:

    Wie soll ich denn alles löschen, was ich via new erstellt habe?

    "erstellen", schon wieder 😡

    1. man "erstellt" nichts mit new .
    2. man allokiert tunlichst nichts mit new .
    3. gibt es smart pointer.


  • erstellen...
    to build sth.
    to compile
    to construct sth.
    to create sth.
    ...

    Was genau regt dich jetzt auf?
    Was wären die deiner Meinung nach akzeptablen Formulierungen?



  • Fachchinesisch wäre es "Ein Objekt auf dem Heap erzeugen"...



  • Die erinnerung schrieb:

    Fachchinesisch wäre es "Ein Objekt auf dem Heap erzeugen"...

    Ischt mir schon klar.
    Ich will nur wissen was an "erstellen" jetzt SO furchbar bzw. ärgerlich ist, dass man nen 😡 dazumalt.

    Wobei, wenn man es schon so genau nimmt, dann geht Heap auch nicht. Weil "free store" != "heap" und so 🤡



  • Slux schrieb:

    Wieso sollte kein delete vorkommen? Wie soll ich denn alles löschen, was ich via new erstellt habe?

    Google mal nach "Smart pointer"


  • Mod

    Ich habe Schwierigkeiten zu glauben, das Ganze könnte etwas anderes sein als ein Trollpost.



  • Slux schrieb:

    Wieso sollte kein delete vorkommen? Wie soll ich denn alles löschen, was ich via new erstellt habe?

    Das sollst du gar nicht selbst. Das sollen andere Objekte für dich tun. Deligiere diese Verantwortung möglichst früh von dir weg und du ersparst dir viel Ärger. Die Klassen dieser anderen Objekte verwenden dann irgendwo intern mal delete.

    Siehe
    - Boost Pointer Container
    - std::unique_ptr
    - std::shared_ptr und std::weak_ptr

    camper schrieb:

    Ich habe Schwierigkeiten zu glauben, das Ganze könnte etwas anderes sein als ein Trollpost.

    Die Fragen von Slux? Hmm...
    *mit-den-schultern-zuck*



  • hustbaer schrieb:

    Ich will nur wissen was an "erstellen" jetzt SO furchbar bzw. ärgerlich ist, dass man nen 😡 dazumalt.

    Swordfish schrieb:

    Patrick_C64 schrieb:

    [...] auch wenn Fachlich vllt. unpassend!)

    Mir geht's garnicht um "fachlich richtig" - mich kotzt's nur an, daß heutzutage /alles/, Grafiken, Websites, ... Spiele (<- !! Da gibt's dann Fragen à la "Mit welchem Programmierprogramm kann ich denn ein Spiel erstellen?") ... E R S T E L L T wird. Am besten aus dem Nichts: "Wo muss ich klicken?", "Hab' ich gemacht, geht nicht!!", ...


  • Mod

    Swordfish schrieb:

    hustbaer schrieb:

    Ich will nur wissen was an "erstellen" jetzt SO furchbar bzw. ärgerlich ist, dass man nen 😡 dazumalt.

    Swordfish schrieb:

    Patrick_C64 schrieb:

    [...] auch wenn Fachlich vllt. unpassend!)

    Mir geht's garnicht um "fachlich richtig" - mich kotzt's nur an, daß heutzutage /alles/, Grafiken, Websites, ... Spiele (<- !! Da gibt's dann Fragen à la "Mit welchem Programmierprogramm kann ich denn ein Spiel erstellen?") ... E R S T E L L T wird. Am besten aus dem Nichts: "Wo muss ich klicken?", "Hab' ich gemacht, geht nicht!!", ...

    Kann ich nicht so ganz nachvollziehen. In Unkenntnis des richtigen Begriffs (oder Unwilligkeit, sich korrekt genau auszudrücken) wird eben ein generisches Wort verwendet. Das ist ein Vorteil für uns: weil es auch eine Aussage über das Niveau ist, mit der geantwortet werden sollte (oder ob überhaupt).



  • Ich wüsste auch nicht wie man bei z.B. Grafiken oder Webseiten sonst sagen sollte. Also ein Wort das nicht festlegt welche Tools genau verwendet werden, ob die Webseite dynamisch ist etc. - was sonst ausser "erstellen"?

    Willst du Grafiken "erzeugen"? Klingt für mich falsch. Malen ist genau so falsch wenn man Renderings erstellt (*g*), zeichnen auch ... ... ?
    Selbst "rendern" ist falsch wenn man Renderings baut (<- besser?), weil das eigentlche rendern ja nur ein kleiner Teil der Arbeit ist.

    Also ... schlag eine Alternative vor. Ich kenne keine (also bei den zuletzt genannten Dingen, bei "new" kann man natürlich "erzeugen" sagen, das ist klar).

    ps: produzieren? machen? bauen? erschaffen?



  • Vielleicht bin ich diesbezüglich ein wenig (über-) sensibilisiert. Mein Deutschlehrer hat zB. schon in der Unterstufe das verb "machen" verteufelt - "Es gibt immer bessere Alternativen!".

    Websiten erstellen:
    Ein Designer wird sich zuerst mit dem Layout auseinandersetzen - er entwickelt/entwirft/gestaltet/... das Design.
    Ein Concept Artist/UI-Designer wird sich mit Bedienkonzepten beschäftigen - er konzipiert/modelliert/... ein UI-Concept.
    Ein Datenbankmensch wird sich mit Datenbankmodellen beschäftigen - er modelliert.
    Ein Webdesigner (im Codeäffchen-Sinn) implementiert - nach Vorgabe von Designkonzepten.

    // ich schreib' später weiter.



  • @Swordfish
    Hast du mich jetzt absichtlich falsch verstanden? 🤡
    Also nochmal...

    Sagen wir da ist Herr X, und Herr X will ne subbi tolle Webseite.
    Herr X hat von Kombuddah und Krafik keine Ahnung. Herr X schreibt also folgende Kleinanzeige:

    Herr X schrieb:

    [Einleitendes Gesülz]

    Ich suche jemanden der eine schöne Webseite für mich [XXXXXX] kann.

    [Weiteres Gesülz über Modalitäten etc.]

    Herr X könnte einfach "machen" verwenden, aber da er nicht als dummer Prolet rüberkommen will gefällt ihm das nicht.

    Was soll Herr X also für [XXXXXX] einsetzen?

    ----

    Swordfish schrieb:

    Vielleicht bin ich diesbezüglich ein wenig (über-) sensibilisiert. Mein Deutschlehrer hat zB. schon in der Unterstufe das verb "machen" verteufelt - "Es gibt immer bessere Alternativen!".

    Lustig, ich finde "machen" eigentlich toll. Ja, es gibt immer Alternativen, fragt sich nur ob die besser sind.
    Ich perzipiere (hust) nämlich Formulierungen wie "ein Konzept konzipieren" als total schwachfüglich 🤡

    ps: Und nochmal Konkret nachgefragt: Der Grafiker ______ eine Grafik?



  • Das einzige was mich an "erstellen" stört, ist dass das im Microsoft-Deutsch die Übersetzung von "build" ist. Hoffentlich glaubt niemand, dass echte Entwickler so reden.



  • Wie würdest du "build" in dem Zusammenhang übersetzen? Bauen? 🙂

    Kompilieren ist ja nur ein Teil vom ganzen Buildvorgang.


Anmelden zum Antworten