Klasse operator= sich selbst löschen?



  • Hallo,

    Ich versuche gerade eine Klasse zu erstellen welche hinter sich aufräumt.
    Ziel ist es die (globale) Variable "stadt" einfach "überschreiben" zu können ohne vorher delete ausrufen zu müssen. Mir ist klar das er Code so nicht gehen kann, weil mein Verstand mir sagt "Wenn ich in einer Member-funktion bin, kann ich diese Klasse nicht löschen". Aber vielleicht gibt es ja doch einen weg. Der operator-> ist dafür da, das man auch Zugriff hat als währe stadt ein Pointer.

    class City
    {
    protected:
    	City *ptr;
    	std::wstring name;
    
    public:
    	City(std::wstring name) : ptr(this)
    	{
    		this->name = name;
    	}
    
    	City* operator->()
    	{
    		return this;
    	};
    
    	City& operator=(City &ref)
    	{
    		std::wcout << "operator=\n";
    		if (this != &ref)
    		{
    			std::wcout << "operator= ... if ...\n";
    
    			// Alle möglichen aufräumarbeiten + speicher frei geben
    			delete this->ptr;
    
    			return ref;
    		}
    		else
    		{
    			std::wcout << "operator= ... same ...\n";
    		}
    
    		std::wcout << "operator= ... return ...\n";
    		return *this;
    	};
    
    	const std::wstring getName()
    	{
    		return this->name;
    	}
    };
    
    	// 1. Test OK
    	City stadt= City(std::wstring(_T("berlin")));
    
    	std::wcout << "Stadt: " << stadt->getName() << "\n";
    
    	// 2. Test, OK
    	stadt = stadt;
    
    	// 3. Test, Error
    	stadt = City(std::wstring(_T("köln")));
    


  • Das geht schon und wird auch gemacht, aber eigentlich sollte man das alte Objekt (nicht Klasse) nicht löschen, sondern mit neuen Werten überschreiben, dann entstehen auch keine Speicherlecks. Wenn du einen nicht trivialen Destruktor hast, würde ich den = Operator spontan als private deklarieren, aber da wäre glaube die Meinung von jemanden erfahreren gefragt.



  • wenn ich ihn private mache, kann ich ja nicht mehr irgendwo stadt = XY machen.
    Aber das ist auch eine Idee, einfach das Objekt leer machen und neu beschreiben.



  • Da hat man doch dann den Destruktor im Prinzip 2 mal implementiert? Oder kann man ihn manuell aus der Klasse aufrufen?

    Du bekommt in der letzen Zeile glaube auch den Fehler, weil du genau das versuchst: das Objekt zu zerstören in dem Objekt selbst. Aber helfen würde es schon, wenn du die genaue Fehlermeldung postest.



  • Ein Objekt, das nicht mit new erzeugt wurde, darf auch nicht mit delete zerstört werden. Das delete hat da in operator= also nichts verloren.

    Ein Zuweisungsoperator sollte etwa so aussehen:

    City& operator=(const City& rhs)
    {
        if (this!=&rhs)name=rhs.name;
        return *this;
    }
    

    Erfüllt ptr eigentlich eine spezielle Funktion?



  • operator= ist ja nicht der destructor, man könnte das z.B. ja auch verwenden um das Objekt mit Daten zu füllen.

    _BLOCK_TYPE_IS_VAILD(pHead->nBlockUse)

    Ich schrieb bereits das es mir einleuchtet dass ich das Object nicht in dem Objekt selber löschen kann. Darum war ja meine frage wie man das lösen würde.

    Ich dachte sogar das ich mit delete Speicherleaks verhinder 😕

    @abc:

    Nein hat er nicht, aber würde genau das jetzt nicht ein Speicherleak verursachen. Weil eben die alten Daten nicht gelöscht werden?



  • MrSpoocy schrieb:

    Weil eben die alten Daten nicht gelöscht werden?

    Welche alten Daten? Es handelt sich nach wie vor um dasselbe City-Objekt, egal wie oft du operator= aufrufst. Falls du name meinst: wie jede andere Klasse hat auch std::wstring dafür zu sorgen, dass eine Neuzuweisung kein Speicherleck verursacht.



  • #include <iostream>
    
    class City
    {
    protected:
        std::wstring name;
    
    public:
        City(std::wstring name) : name(name){}
    
        std::wstring getName() const
        {
            return name;
        }
    };
    
    int main()
    {
        City stadt= City(L"berlin");
    
        std::wcout << "Stadt: " << stadt.getName() << "\n";
    
        stadt = stadt;
    
        stadt = City(L"köln");
        std::wcout << "Stadt: " << stadt.getName() << "\n";
    }
    

    Dann definiere mal, warum du es nicht so machst, dann bekommst du möglicherweise eine hilfreiche Antwort.



  • Naja, die Klasse ist jetzt sehr simpel gezeigt, sie ist größer, und erhält im laufe der Zeit viel mehr Daten druch setMethoden. Ich wollte delete nehmen um einfach alle Werte zu löschen und ein komplett neues sauberes Object zu erhalten. Andernfalls muss ich jeden wert wieder zurück setzen 😕



  • MrSpoocy schrieb:

    Naja, die Klasse ist jetzt sehr simpel gezeigt, sie ist größer, und erhält im laufe der Zeit viel mehr Daten druch setMethoden. Ich wollte delete nehmen um einfach alle Werte zu löschen und ein komplett neues sauberes Object zu erhalten. Andernfalls muss ich jeden wert wieder zurück setzen 😕

    Warum sollte es nötig sein, etwas zurückzusetzen? Es werden alle Werte der neuen Stadt kopiert!



  • MrSpoocy schrieb:

    Naja, die Klasse ist jetzt sehr simpel gezeigt, sie ist größer, und erhält im laufe der Zeit viel mehr Daten druch setMethoden. Ich wollte delete nehmen um einfach alle Werte zu löschen und ein komplett neues sauberes Object zu erhalten. Andernfalls muss ich jeden wert wieder zurück setzen 😕

    operator= soll das Objekt nicht zurücksetzen, sondern muss die Attribute des übergebenen Objekts kopieren (name usw.).
    Die gute Nachricht ist, dass du das in aller Regel nicht selbst machen musst, denn der Compiler erzeugt einen passenden operator= wenn du keine eigene Definition angibst.
    Wenn du ihn also einfach ganz weglässt, wirst du sehen, dass dein Code nun korrekt funktioniert. Und es gibt auch keine Speicherlecks.


Log in to reply