viele Instanzen erzeugen
-
Hallo.
Ich habe eine Klasse namens Auto von der ich viele Instanzen erzeugen möchte.
Mithilfe eines Arrays ginge das natürlich, aber da Autos auch jederzeit wieder entfernt bzw. neue hinzugefügt werden müssen, habe ich einen std::vector genommen.
Mittels push_back() kann ich dann über eine bereits vorhandene Instanz Kopien davon erzeugen. Das ganze funktioniert aber nicht wie ich es mir vorgestellt habe.
Die Instanzen werden anscheinend nicht erzeugt, sondern nur kopiert (Instanzenzähler bleibt auf 1).
Kurz gesagt: Wie erzeuge ich eine große Anzahl Instanzen richtig und kann dann noch weitere hinzufügen und entfernen?#include <iostream> #include <vector> int AnzAutos = 0; int main() { class Auto { public: int Geschwindigkeit; Auto() { AnzAutos++; Geschwindigkeit = 200; } }; Auto Auto1; std::vector<Auto> Autosammlung; for(int i = 0; i < 100; i++) { Autosammlung.push_back(Auto1); } std::cout << "AnzAutos = " << AnzAutos; // = 1 std::cout << "\nAutosammlung[87].Geschwindigkeit = " << Autosammlung[87].Geschwindigkeit; // = 200 return 0; }
-
Oh, Du hast zwar nur eine Instanz direkt erstellt, die aber im Vektor vervielfältigt, so dass Du nun ganz viele Instanzen hast:
#include <iostream> #include <vector> int AnzAutos = 0; int main() { class Auto { public: int Geschwindigkeit; Auto() { AnzAutos++; Geschwindigkeit = 200; } }; Auto Auto1; std::vector<Auto> Autosammlung; for(int i = 0; i < 100; i++) { Autosammlung.push_back(Auto1); } std::cout << "AnzAutos = " << AnzAutos; // = 1 std::cout << "\nAutosammlung[87].Geschwindigkeit = " << Autosammlung[87].Geschwindigkeit; // = 200 //Sieh hier: std::cout << "\nAnzahl: " << Autosammlung.size() << '\n'; for(int i = 0; i < Autosammlung.size(); ++i) Autosammlung[i].Geschwindigkeit = i; std::cout << "\nAuto 5 Geschwindigkeit: " << Autosammlung[5].Geschwindigkeit << '\n'; std::cout << "\nAuto 87 Geschwindigkeit: " << Autosammlung[87].Geschwindigkeit << '\n'; return 0; }
-
Wenn du wirklich willst, dass der Konstruktor für jedes Auto das du hinzufügst neu aufgerufen wird musst du die Autos so hinzufügen:
for(int i = 0; i < 100; i++) { Autosammlung.push_back(Auto()); }Dann wird AnzAutos auch deiner Anzahl hinzugefüger Autos entsprechen. Allerdings ist das wenig sinnvoll sich so die Anzahl der Autos zu merken (wenn der überhaupt Ziel ist). Der std::vector speichert sich die Anzahl der hinzugefügten Objekte schon selbst.
Kinemeier schrieb:
aber da Autos auch jederzeit wieder entfernt bzw. neue hinzugefügt werden müssen, habe ich einen std::vector genommen.
Das entfernen von Autos ist mit std::vector in etwa genauso umständlich wie bei Arrays. Zumindest wenn du mitten drin Autos entfernen willst weil du dann alle Autos die noch folgen umkopieren musst.
-
sebi707 schrieb:
Das entfernen von Autos ist mit std::vector in etwa genauso umständlich wie bei Arrays. Zumindest wenn du mitten drin Autos entfernen willst weil du dann alle Autos die noch folgen umkopieren musst.
Anscheinend ist hier die Reihenfolge nicht wichtig, daher kommt man auch mit einer einzelnen Verschiebung aus.
-
Was Du u.U. noch nicht weißt: es gibt neben dem Konstruktor, den Du implementiert hast noch weitere.
Dein Konstruktor - der ohne Argumente wird default-constructor genannt.push_back()in Deinem Code fügt allerdings eine Kopie vonauto1an denvectoran. Um die Kopie zu erstellen benutzt es den copy-constructor.
Da Du keinen copy-c'tor geschrieben hast, wird einer vom Compiler generiert. Der sieht ungefähr so aus:class Auto { .... wie zuvor Auto(const Auto& other) // copy-ctor { Geschwindigkeit = other.Geschwindigkeit; } };Wie Du siehst: da wird
anzAutosnicht inkrementiert. Klar, eigentlich - der Compiler kann ja nicht Deine Gedanken lesen! (Aber er kann doof jedes member kopieren...)Spendier
Autoeine Kopierkonstruktor, deranzautosinkrementiert: et voilà."Et voilà" with a twist: Du wirst feststellen, dass
AnzAutoenorm groß wird - im Gegensatz zur Größe des Vektors.Das liegt daran, dass im Hintergrund fröhlich Autos hin und her kopiert werden, wenn der Vektor sich vergrößert, weil er mehr Speicherplatz braucht.
In diesem Moment alloziert der vector neuen (und größeren) Speicherplatz, kopiert jedes Element an seinen neuen Platz und löscht schließlich die alten Elemente. Dafür wird deren destructor aufgerufen.
Dementsprechend musst DuAnzAutosnoch im destructor von Auto um 1 verringern.Viel zu lernen...

Es lohnt sich!
-
Du kannst auch übrigens einfach Autosammlung.size() nehmen um die Anzahl der Autos innerhalb des vectors zu erfragen.
-
Danke für Eure zahlreichen Antworten.
sebi707 schrieb:
for(int i = 0; i < 100; i++) { Autosammlung.push_back(Auto()); }Genau so habe ich mir das vorgestellt.
Ziel der ganzen Sache ist es, dass ich erst einmal x Instanzen anlege,
geänderte Werte (Lackierung, Kilometerzähler etc.) aus einer Datei einlese,
dann während des Spiels Autos entferne, hinzufüge und verändere und am Ende alles wieder abspeichere.
Das sollte ich nun hinbekommen.
-
Man könnte statt dessen auch einfach.
std::vector<Auto> Autosammlung(100);schreiben.
-
Oh ja, das läuft sogar noch viel schneller.
(Habe allerdings alle Compileroptimierungen deaktiviert.)
-
std::vector<Auto> autosammlung; autosammlung.reserve(100); for(std::size_t i = 0; i < 100; i++) { autosammlung.push_back(Auto()); }Dürfte ähnlich schnell laufen und so kannst du sogar unterschiedliche Autos im vector haben, falls du mal einen anderen Konstruktor hinzufügst.
-
Kinemeier schrieb:
Oh ja, das läuft sogar noch viel schneller.
(Habe allerdings alle Compileroptimierungen deaktiviert.)Stoppst du mit einem extra Programm die Zeit oder hast du mit mehreren Elementen Millionen Elementen gestestet? Bei 100 Elementen dürfte selbst mit Optimierungen deaktiviert das Programm sofort fertig sein.
-
Ja, habe es mit 100 Millionen getestet.
Die Zeiten schwanken zwar enorm, aber das Ergebnis ist trotzdem eindeutig.
-
Niemanden interessiert, wie schnell unoptimierter Code läuft.