[Gelöst]Shared_Ptr Klasse



  • Hallo, ich habe versucht die Shared_Ptr Klasse selbst zu definieren jedoch erhalte ich eine Fehlermeldung:

    Ausnahmefehler bei 0x013A3FA5 in Projekt6.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000

    HasPtr.h

    #ifndef HASPTR_INCLUDED
    #define HASPTR_INCLUDED
    #include <string>
    #include <iostream>
    using namespace std;
    
    class HasPtr
    {
    public:
    	// Konstruktoren
    	HasPtr() = default;
    	HasPtr(const string&);
    	HasPtr(const HasPtr&);
    	HasPtr& operator=(const HasPtr&);
    
    	// Destruktor
    	~HasPtr();
    
    	// Ausgabe Attribute
    	void ausgabe() const;
    private:
    	// Attribute
    	int* benutzer;
    	string* name;
    };
    
    // Konstruktor
    HasPtr::HasPtr(const string& Name) : name(new string(Name)), benutzer(new int(1))
    {
    
    }
    
    // Kopierkonstruktor
    HasPtr::HasPtr(const HasPtr& HObjekt)
    {
    	if (&HObjekt != this)
    	{
    		++*HObjekt.benutzer;
    		if (--*benutzer == 0)
    		{
    			delete benutzer;
    			delete name;
    		}
    		benutzer = HObjekt.benutzer;
    		name = HObjekt.name;
    	}
    }
    
    // Zuweisungskonstruktor
    HasPtr& HasPtr::operator=(const HasPtr& HObjekt)
    {
    	if (&HObjekt != this)
    	{
    		++*HObjekt.benutzer;
    		if (--*benutzer == 0)
    		{
    			delete benutzer;
    			delete name;
    		}
    		benutzer = HObjekt.benutzer;
    		name = HObjekt.name;
    	}
    
    	return *this;
    }
    
    // Destruktor
    HasPtr::~HasPtr()
    {
    	if (--*benutzer == 0)
    	{
    		delete benutzer;
    		delete name;
    	}
    }
    
    // Ausgabe 
    void HasPtr::ausgabe() const
    {
    	std::cout << "\n---------------------------------------------\n";
    	std::cout << "Benutzer Name:" << *name << std::endl;
    	std::cout << "Benutzer Zaehler:" << *benutzer << std::endl;
    	std::cout << "---------------------------------------------\n";
    }
    #endif
    

    Main.cpp

    #include "HasPtr.h"
    
    int main()
    {
    	HasPtr MainObjekt("Test 1");
    	HasPtr NebenObjekt1(MainObjekt);
    	HasPtr NebenObjekt2(MainObjekt);
    
    	MainObjekt.ausgabe();
    }
    


  • Wenn du in der main in Zeile 6 den Kopierkonstruktor aufrufst, welchen Wert hat dann benutzer in Zeile 39?
    Die Frage soll dazu dienen dir Gedanken darüber zu machen, was du da in 39 bis 43 eigentlich machst und inwiefern das notwendig ist.



  • Einen undefinierten, vielen Dank.
    Edit: Ich glaube das ich entweder den Attrubuten Startwerte zuweisen muss(in der Klasse) oder der Kopierkonstruktor ein name und benutzer der klasse neu anlegen muss.



  • TemplateQ schrieb:

    Edit: Ich glaube das ich entweder den Attrubuten Startwerte zuweisen muss(in der Klasse) oder der Kopierkonstruktor ein name und benutzer der klasse neu anlegen muss.

    Wieso musst du überhaupt den alten Count dekrementieren? Die Klasse kann ja zu dem Zeitpunkt keine Resource besitzen, also musst du auch nichts freigeben. Alles was du machen musst ist die Pointer vom anderen Objekt herüber zu kopieren und den gemeinsem count-Pointer erhöhen.

    Das du std::string nicht mit new anlegen musst ist dir aber hoffentlich bewusst?



  • [quote="Nathan"]

    TemplateQ schrieb:

    Das du std::string nicht mit new anlegen musst ist dir aber hoffentlich bewusst?

    Das Attribut name ist ein Zeiger auf ein string Objekt und Zeiger muss man mit new anlegen oder habe ich da etwas falsch verstanden?



  • [quote="TemplateQ"]

    Nathan schrieb:

    TemplateQ schrieb:

    Das du std::string nicht mit new anlegen musst ist dir aber hoffentlich bewusst?

    Das Attribut name ist ein Zeiger auf ein string Objekt und Zeiger muss man mit new anlegen oder habe ich da etwas falsch verstanden?

    (nitpicky: new "legt keinen Zeiger an" sondern ein Objekt und liefert dann einen Zeiger darauf zurück.)

    Aber warum überhaupt Zeiger als Member? * enfernen, new entfernen und glücklicher sein als vorher.

    Das ist kein Java, man kann sachen auch ohne new erzeugen.



  • Uch habe einen Zeiger als member damit bei änderungen auch die Objekte die auf die Klasse zeigen geupdatet werden, sonst wird doch rein theoretisch nur die Kopie übergeben.



  • Ein Zeiger ist schon ok. Aber fasse besser beide Verwaltungsdaten zusammen:

    class HasPtr
    {
    public:
        // Konstruktoren
        HasPtr() = default;
        HasPtr(const string&);
        HasPtr(const HasPtr&);
        HasPtr& operator=(const HasPtr&);
    
        // Destruktor
        ~HasPtr();
    
        // Ausgabe Attribute
        void ausgabe() const;
    private:
        struct SharedData {
          int count;
          string name;
        };
        SharedData *ptr;
    };
    


  • Guck dir das Copy&Swap Idiom an.
    Das passt hier perfekt.



  • Vielen Dank, das werde ich tun!


Log in to reply