Klassen - Objekte - Zeiger und Listen



  • Hi - habe ein bisschen gesucht und durchgelesen aber bei meinem Problem bin ich nicht wirklich weiter gekommen.

    Ich habe zwei Klassen, die ich erstellen möchte. Die eine erstellt Items, die andere soll dieses verwalten.

    Immer, wenn ich eine Klasse erstelle, speichere ich das Objekt in einer Liste. (hatte dort erst auch nur einen pointer gespeichert) - nunja.. Jetzt möchte ich aus der Liste das Objekt raussuchen und dann über die Item-Klasse löschen.

    class A{
         list<Item> spiele = list<Item>();
    
         void addSpiel(string titel, int sZahl, int alter){
                pointer = new Item(titel, sZahl, alter, id);
                spiele.push_back(*pointer);
         }
    
         bool entferneItem(int id){
                 for(auto i = spiele.begin(); i != spiele.end(); i++){
                    if(*i->getID() == this->id){
                        delete *i;
                        spiele.erase(i);
                        
                        return true;                      
                    }
         return false;
         }
    

    Jetzt bekomme ich folgende Fehlermeldung :
    error: cannot delete expression of type 'std::_List_iterator<Item>'
    delete i;

    Ich habe das ganze aber auch probiert über pointer .. aber verstehe nicht ganz wieso es nicht funktioniert. Mein Gedanke ist/war, dass durch auto i hier automatisch den Datentyp des Objekts übernimmt und dann dieses Objekt löscht. Oder muss ich doch komplett umbauen, darf gar keine Objekte in der Liste speichern, sondern nur zeiger?

    Danke für jede Hilfe
    bobbgott



  • Warum nutzt du überhaupt Pointer? Du hast doch eine list<Item>, also eine Liste von Items, nicht eine Liste von Item-Pointern! Kommst du aus einer anderen Sprache, wo man alle Objekte mit new anlegen muss? In C++ ist das nicht der Fall. Du kannst du ein Item ohne Pointer anlegen.

    Lösche das new und auch das delete vollständig aus deinem Code.
    Das addSpiel wird:

    Item item(titel, sZahl, alter, id);
    spiele.push_back(item)
    

    oder direkt

    spiele.emplace_back(titel, sZahl, alter, id);
    

    Noch 3 andere Dinge:

    • Was ist das this->id in Zeile 11 (if(*i->getID() == this->id){)? Willst du nicht lieber mit dme Parameter id vergleichen?
    • Was soll list<Item> spiele = list<Item>(); tun? Warum nicht einfach den Teil rechts vom Gleich-Zeichen löschen? Also einfach nur list<Item> spiele;! (zu viel Java gemacht?)
    • Warum list statt vector? (zu viel Java gemacht? ArrayList?)


  • Danke erstmal für die Antwort.
    Ja, ich komme aus Java aber das ist auch nun schon 5 Jahre her.

    Wenn ich new und delete streichen soll, wie zerstöre ich denn ein Objekt?
    Und was ist der Mehrwert dies nicht zu benutzen. New erstellt und hält doch nur den Speicherplatz konstant be reicht, dachte ich?
    Oder muss ich es dafür nur aus der Liste mit erase() nehmen?


    Die Zeile 11 war ein Versuch ein bestimmtes Objekt zu löschen.
    Die Grundidee war, dass der User sagt ich möchte Objekt mit ID XYZ löschen.

    Also gehe Ich meine Liste durch mit ner linearen suche , ziehe zu jedem die id raus und Vergleiche sie mit meiner vom User gegebenen.


    Dass der rechte Teil der liste nicht notwendig ist, habe ich mir schon fast gedacht aber aus einem beispiel übernommen. Dachte ggf darf die liste nicht anders erstellt werden.
    Aber code reduzieren etc würde bei mir am ende eh nochmal kommen 🙂

    Edit: achso und pointer.. Ja gut. Das habe ich vorher immer bei SVG Objekten benutzt und daher versucht damit mein Problem zu beheben.



  • @bobbgott sagte in Klassen - Objekte - Zeiger und Listen:

    Oder muss ich es dafür nur aus der Liste mit erase() nehmen?

    Ja, das reicht. Es ist ja kein Pointer!

    Anders wäre es, wenn du eine list<Item*> (mit *) hättest. Dann wären das ja alles Pointer und du müsstest das Objekt selber löschen. Aber: verwende weder new noch delete in C++ (sofern du nicht gerade eine Speicherverwaltungsklasse baust) (siehe auch)! Wenn du dynamischen Speicher brauchst, dann nimm Smart Pointer (erstellen mit std::make_unique oder std::make_shared). Kümmere dich nicht manuell um Speicherverwaltung. Du wirst es nämlich garantiert falsch machen. Nimm immer die dafür gedachten Container-Klassen.

    Und was ist der Mehrwert dies nicht zu benutzen. New erstellt und hält doch nur den Speicherplatz konstant be reicht, dachte ich?

    New erstellt den Speicher UND ruft den Konstruktor des Objektes auf UND gibt dir danach einen Pointer in deinen Verantwortungsbereich und DU musst dich darum kümmern, den Speicher irgendwann (aber nur genau 1x) wieder freizugeben. Das ist SEHR SEHR fehleranfällig. Siehe den oben verlinkten Artikel der CPP Core Guidelines.



  • Danke - werde mir den Artikel mal durchlesen. Ist denke ich aktuell noch dem ganzen geschuldet, dass es eine Anfängeraufgabe ist und man manches nutzen soll um es zu verstehen, auch wenn es hier nicht das beste ist.

    Da du aber bereits Zeile 11.. If( i->getId...) angesprochen hast. Ist dies denn falsch?
    Also this-> id habe ich benutze, da ich oebn ein weiteres id für die Add habe.
    Und *i da ich die Objekte ansprechen wollte und nicht den Listenspeicherplatz... Oder ist das dann auch falsch, wenn ich die Objekte ohne New erstelle und das Objekt direkt in der Liste Speicher

    Vielen dank im Voraus wie immer

    EDIT :
    Also i->getID() ist scheinbar falsch.... als ich i.getId() ausprobiert habe, hat aber auch der Compiler gemeckert und mit "->" vorgeschlagen.
    Dennoch bekomme ich dort immer 0 raus. Falls jemand helfen kann 🙂


Anmelden zum Antworten