Klasseninstanz aus Vector löschen
-
Hallo,
ich hab eine Vector-Liste, in der Klasseninstanzen gespeichert sind:#include <iostream> #include <string> #include <vector> class Vehikel { int Raeder; float Gewicht; }; std::vector<Vehikel> Fahrzeuge; int main() { for(int i = 0; i < 1000; i++) { Fahrzeuge.push_back(*(new Vehikel())); } std::cout<<"Bis hier\n"; for(std::vector<Vehikel>::iterator dIter(Fahrzeuge.begin()); dIter != Fahrzeuge.end(); ++dIter) { delete dIter; dIter = Fahrzeuge.erase(dIter); } return 0; }Das soll nur ein Bespielprogramm bei dem der Fehler auftritt. Er legt die Vectorreihe wie gewohnt an, aber beim löschen gibt es eine Fehlermeldung, ich glaube ein Assert. Weiß jemand vielleicht wo der Fehler liegt?
Vielen Dank für eine Antwort, viele Grüße
Andreas
-
Hallo,
Das geht so nicht. Du versuchst immerhin einen Iterator zu löschen. Warum erzeugst du die Instanzen überhaupt mit new wenn du einen vector auf Objekte hast? Lass das einfach weg.
std::vector<Vehikel> Fahrzeuge; int main() { for(int i = 0; i < 1000; i++) { Fahrzeuge.push_back(Vehikel()); } std::cout<<"Bis hier\n"; // statt der Schleife reicht auch ein Fahrzeuge.clear(); for(std::vector<Vehikel>::iterator dIter(Fahrzeuge.begin()); dIter != Fahrzeuge.end(); ++dIter) { dIter = Fahrzeuge.erase(dIter); } return 0; }Falls du einen vector auf Zeiger von Vehikel hättest würde löschen so aussehen.
delete *dIter; //einfach dereferenzieren
-
Hi,
danke für die Antwort.
Aber ich hatte das bisher immer so verstanden, dass man größere Datenmengen mit new erzeugen soll, damit sie nicht den Stack so belasten (ich muss zugeben so genau kenn ich mich mit Heap und Stack nicht aus).
Deshalb dachte ich muss ich die Objekte in meinem Programm mit new erzeugen, da sie schon recht groß sind und es viele werden können ( Das andere war nur ein Beispiel-Programm, die echten Klassen sind wesentlich komplexer)Viele Grüße
Andreas
-
Andreas_L schrieb:
Deshalb dachte ich muss ich die Objekte in meinem Programm mit new erzeugen, da sie schon recht groß sind und es viele werden können ( Das andere war nur ein Beispiel-Programm, die echten Klassen sind wesentlich komplexer)
Das ist zu undifferenziert betrachtet. Du kannst natürlich keine Arrays großer Objekte auf dem Stack anlegen, aber letztlich ist alles, was eine variable Größe hat, irgendwo im Freispeicher abgelegt. D.h. auch wenn der Vector auf dem Stack liegt, liegen die vom Vector verwalteten Daten nicht dort.
Davon ab speicherst Du in Deinem Code sowieso keine mit new erzeugten Objekte im Vector, sondern Kopien derselben (die mit new erzeugten Objekte sind danach übrigens verloren, sprich hier ist ein Leck). Allein deshalb funktioniert delete auf den Iterator schon nicht.
Du könntest zwar Zeiger auf die Objekte im Vector speichern, aber ich bin mir recht sicher, dass Du unter Beachtung aller Tatsachen das nicht wirklich möchtest.
-
Hi,
heißt das auch wenn ich mehrfach
Fahrzeuge.push_back(Vehikel());
aufrufe und Vehikel sehr groß ist brauch ich keine Angst vor einem Stack-Error zu haben?
Ich brauch mich auch nicht weiter um das Objekt kümmern, wenn ich erase aufrufe wird automatisch de Destruktor von Vehikel aufgerufen?Viele Grüße
Andreas
-
Exakt.
-
Hi,
eine letzte Frage noch
ich hab den Code etwas verändert:#include <iostream> #include <string> #include <vector> class Vehikel { int Raeder; float Gewicht; public: Vehikel(){ std::cout<<"Im Konstruktor!\n";} ~Vehikel() { std::cout<<"Im Destruktor!\n";} }; std::vector<Vehikel> Fahrzeuge; int main() { for(int i = 0; i < 10; i++) { Fahrzeuge.push_back(Vehikel()); } std::cout<<"Bis hier\n"; for(std::vector<Vehikel>::iterator dIter(Fahrzeuge.begin()); dIter != Fahrzeuge.end(); ++dIter) { dIter = Fahrzeuge.erase(dIter); } return 0; }Wenn ich zu Beginn den Destruktor auskommentiere kommt wie erwartet 10 mal die Ausgabe "Im Konstruktor".
Nehme ich jetzt aber den Destruktor hinzu kommt so eine Ausgabe:Im Konstruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Konstruktor!
Im Destruktor!
Bis hier
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!
Im Destruktor!Was soll das?
Das müssten 10 mal "im Konstruktor" und 30 mal "im Destruktor" sein. Wenn er jedesmal eine Kopie anlegt kann ich das ja noch verstehen, aber wieso gleich 30 mal?
Meine einzige Erklärung wäre, er legt das Objekt an, übergibt es als Kopie der Methode, dann wird es zum ersten Mal gelöscht. Im weiteren Verlauf speichert die Methode eine Kopie davon in der Vectorreihe; es wird das 2. Mal gelöscht. Das dritte Mal würde dann durch mein erase() geschehen. Aber dann lässt sich nicht erklären, warum nach "Bis hier" nur noch 5 mal die Meldung kommt und nicht 10 mal, schließlich will ich ja 10 Objekte löschen.Ansich ist mir ja seine Speicherumwälzung egal, aber es sollte halt möglichst schnell gehen und ich habe eigentlich so eine Art Modell bei dem Häuser gebaut werden und die erhöhen dann die Anzahl der möglichen Wohnplätze (eine Variable des Haupt-Spiels). Beim löschen eines Hauses wurde im Destruktur die Anzahl der Wohnplätze dann wieder verringert. Nun stand da auf einmal eine negative Anzahl an Wohnplätzen, was sich mit dieser Ausgabe deckt.
Was hab ich falsch gemacht, wie muss ich es ändern?
Viele Grüße
Andreas
-
Am besten ist es wohl du machst noch eine Ausgabe im CopyKonstruktor. Dann sollte alles klarer werden.
Wenn beim vector der Speicherplatz zum Anfügen eines neuen Objektes nicht ausreicht wird umkopiert. Das kann man verhindern, indem man vor dem Anfügen mit reserve ausreichend Platz reserviert.
Warum nach der erase-Schleife nur 5-mal Destruktor steht? Dann überleg mal was erase zurückgibt und ++dIter bewirkt.