destruktor Vector
-
Hallo,
ich habe eine dynamischen Vektoren erstellt:item = new std::vector<item_group_item>(number);und möchten den Speicher später wieder ordentlich freigeben.
Der Destruktor sieht dafür so aus:
delete item;geb ich dadurch auch wirklich den alle Objekte innerhalb des Vektoren frei?
Oder gibt es einen besseren Weg?
z.Bfor(int i = (item->size()-1); i >= 0;i--){ // delete &item->at(i); item->pop_back(); } delete item; }Hab kp ob das jetzt besser oder schlechter ist.
Und Generel: Auf was sollte ich achten, wenn ich einen Destruktor einer Klasse erstelle. Besonders in hinblick auf Vererbung und Polyphonie usw.
Für Antworten wäre ich sehr dankbar
-
new und vector ist mit äußerster Wahrscheinlich blödsin.
Und selbstverständlich räumt ein std::vector hinter sich auf.
-
Der
std::vector<..>gibt seine Elemente wieder frei bei der Zerstörung.ABER...
Wenn du Zeiger in den
std::vector<..>steckst, werden auch nur die Zeiger freigegeben - nicht jedoch das Objekt auf das sie zeigen. Ob dies nötig ist, hängt davon ab, auf was für Objekte der Zeiger zeigt.Das folgende Beispiel veranschaulicht die verschiedenen Varianten. Die Klasse
Personist um verschiedene Konstruktoren und den Destruktor erweitert worden, so dass man sehen kann, wann welche Objekte erzeugt und wieder zerstört werden.#include <iostream> #include <iomanip> #include <vector> #include <memory> class Person { public: explicit Person(int id) : m_id(id) { std::cout << "Person (ID=" << m_id << ", Addresse=0x" << std::hex << this << std::dec << ") erzeugt (id)\n"; } Person(const Person& other) : m_id(other.m_id) { std::cout << "Person (ID=" << m_id << ", Addresse=0x" << std::hex << this << std::dec << ") erzeugt (copy)\n"; } Person& operator=(const Person&) = delete; Person(Person&& other) : m_id(other.m_id) { std::cout << "Person (ID=" << m_id << ", Addresse=0x" << std::hex << this << std::dec << ") erzeugt (move)\n"; } Person& operator=(Person&&) = delete; ~Person() { std::cout << "Person (ID=" << m_id << ", Addresse=0x" << std::hex << this << std::dec << ") zerstoert\n"; } private: int m_id; }; int main() { { // Die Elemente haben den Typ Person, d. h. beim Zerstören // des std::vector<..> werden die Person-Objekte zerstört. std::vector<Person> persons; persons.push_back(Person{ 17 }); persons.push_back(Person{ 18 }); } { // Die Elemente haben den Typ Person*, d. h. beim Zerstören // des std::vector<..> werden "nur" die Zeiger-auf-Person-Objekte // zerstört, nicht aber die Person-Objekte selbst. Die Person- // Objekte werden allerdings auch automatisch beim Verlassen // des Gültigkeitsbereichs zerstört. Person person27{ 27 }; Person person28{ 28 }; std::vector<Person*> persons; persons.push_back(&person27); persons.push_back(&person28); } { // Die Elemente haben den Typ Person*, d. h. beim Zerstören // des std::vector<..> würden "nur" die Zeiger-auf-Person-Objekte // zerstört, nicht aber die Person-Objekte selbst (weil sie mit new // erzeugt wurden). Deshalb müssen sie manuell freigegeben werden // (mit delete). Das ist fehleranfällig (weil man es vergessen kann oder // Ausnahmen geworfen werden können etc.) und deshalb wählt man meistens // intelligente Zeiger, wie im nächsten Beispiel. Das muss man aber nur, // wenn Objekte im Freispeicher erzeugt werden müssen (mit new oder Verwandten). std::vector<Person*> persons; persons.push_back(new Person{ 37 }); persons.push_back(new Person{ 38 }); // Freigeben der Person-Objekte for (auto person : persons) { delete person; } } { // Die Elemente haben den Typ std::unique_ptr<Person>, d. h. beim Zerstören // des std::vector<..> werden die std::unique_ptr<..> und damit die Person- // Objekte zerstört. std::vector<std::unique_ptr<Person>> persons; persons.push_back(std::make_unique<Person>(47)); persons.push_back(std::make_unique<Person>(48)); } }// Edit
win8789 schrieb:
Und Generel: Auf was sollte ich achten, wenn ich einen Destruktor einer Klasse erstelle. Besonders in hinblick auf Vererbung und Polyphonie usw.
Hehe, kleiner Scherz mit Polyphonie..

Also generell ist es gut, wenn du dafür sorgst, dass kein selbstdefinierter Destruktor nötig ist. D. h. wenn die Resourcen, die eine Klasse besitzt, automatisch wieder aufgeräumt werden, wenn ein Objekt der Klasse zerstört wird, z. B. indem du
std::unique_ptr<..>oder allgemein RAII benutzt.
-
danke Theta,
aber kann ich auch so was machen:std::vector<std::unique_ptr<item_group_item>> item; for(int i = 0; i < number; i++){ item.push_back(std::make_unique<item_group_item>(1)); }//es soll eine beliebe anzahl an einfachen objekten dynamisch im vector erzeugt //werden, die durch den Standartkonstruktor entstehen.und
delete itemfunktioniert wohl später im destruktor nicht. jedenfalls gibt er mir eine Fehlermeldung aus. "kann nicht in void* konvertiert werden".
-
Dein
std::vector<std::unique_ptr<item_group_item>>Namensitemliegt am Stack und wird am Ende des Scopes zerstört. Nixdelete!
-
Swordfish schrieb:
Dein
std::vector<std::unique_ptr<item_group_item>>Namensitemliegt am Stack und wird am Ende des Scopes zerstört. Nixdelete!ok ich will aber, selbst bestimmen wann die objekte zerstört werden, da im programm immer wieder dynamische arrays gebraucht werden und immer wieder gelöscht werden müssen und wieder neue erstellt werden müssen.
-
Vielleicht erzählst lieber mal, was dein Programm den überhaupt können soll und nicht, wie du denkst das am besten zu realisieren.
-
Swordfish schrieb:
Vielleicht erzählst lieber mal, was dein Programm den überhaupt können soll und nicht, wie du denkst das am besten zu realisieren.
Nachporgrammierung des Programms 10 und 10:
Es gibt ein Feld, welche 10 * 10 felder groß ist.Auf diesen Feld kann man Gruppen von Steine Plazieren.
Wenn eine Reihe voll ist, dann verschwiendet sie und es gibt Punkte.
Es kommen so lange zufällige Gruppen von Steine nach, bis es nicht mehr möglich ist eine Gruppe zu plazieren.
Wenn eine Steingruppe platziert ist, sollen Felder die als Container dienen aktiviert werden und die Steingruppe gelöscht werden. gleichzeitig soll nach der Platzierung von drei Steingruppen, drei neue entstehen und angezeigt werden.
Die Container und die möglichkeit, steine Sinnvoll (nur wenn es das Spielfeld zu läst (keine steine auf aktivierte Container, keine Gruppe die über den Rand geht)) zu plazieren ist schon fertig.
-
Da dein Feld immer gleichgroß bleibt, musst du doch nichts dynamisch ändern?
-
Und selbst wenn, kann man den vector einfach als Member der Playfield/Game/... Klasse machen.
Im Dtor muss man dann genau gar nix schreiben, da Member ja bekanntlich mit dem Objekt mit zerstört werden.Vielleicht fehlen win8789 da einfach nur die C++ Grundlagen?
-
win8789 schrieb:
[...] die möglichkeit, steine Sinnvoll (nur wenn es das Spielfeld zu läst (keine steine auf aktivierte Container, keine Gruppe die über den Rand geht)) zu plazieren ist schon fertig.
Spaßeshalber. Zeig mal. Mir schwant Schreckliches.
-
Techel schrieb:
Da dein Feld immer gleichgroß bleibt, musst du doch nichts dynamisch ändern?
das Spielfeld ist auch statisch, nur die Anzahl an Steingruppen ist variabel. So gibt es Gruppen die aus 2 Steine, aus 5 Steinen, 9 Steinen usw. bestehen.
Vielleicht fehlen win8789 da einfach nur die C++ Grundlagen?Was denkst du?
-
win8789 schrieb:
Techel schrieb:
Da dein Feld immer gleichgroß bleibt, musst du doch nichts dynamisch ändern?
das Spielfeld ist auch statisch, nur die Anzahl an Steingruppen ist variabel. So gibt es Gruppen die aus 2 Steine, aus 5 Steinen, 9 Steinen usw. bestehen.
Welche Steine gesetzt wurden interessiert doch nach dem Platzieren keinen mehr. Alleine welche Felder des Spielfelds danach (in welcher Farbe, zur Anzeige) belegt sind, ist relevant.
win8789 schrieb:
hustbaer schrieb:
Vielleicht fehlen win8789 da einfach nur die C++ Grundlagen?
Was denkst du?
jup. Und Programmiererfahrung allgemein.
-
Swordfish schrieb:
win8789 schrieb:
Techel schrieb:
Da dein Feld immer gleichgroß bleibt, musst du doch nichts dynamisch ändern?
das Spielfeld ist auch statisch, nur die Anzahl an Steingruppen ist variabel. So gibt es Gruppen die aus 2 Steine, aus 5 Steinen, 9 Steinen usw. bestehen.
Welche Steine gesetzt wurden interessiert doch nach dem Platzieren keinen mehr. Alleine welche Felder des Spielfelds danach (in welcher Farbe, zur Anzeige) belegt sind, ist relevant.
win8789 schrieb:
hustbaer schrieb:
Vielleicht fehlen win8789 da einfach nur die C++ Grundlagen?
Was denkst du?
jup. Und Programmiererfahrung allgemein.
Ja da hast du wohl recht. Bin halt noch Schüler und muss auch für die Schule was mache. Aber ich versuche halt besser zu werden und in der Schule können die Lehrer nur Java, deshalb mir dort keiner helfen kann.
[quote="win8789"]
Techel schrieb:
Da dein Feld immer gleichgroß bleibt, musst du doch nichts dynamisch ändern?
das Spielfeld ist auch statisch, nur die Anzahl an Steingruppen ist variabel. So gibt es Gruppen die aus 2 Steine, aus 5 Steinen, 9 Steinen usw. bestehen.
Swordfish schrieb:
Spaßeshalber. Zeig mal. Mir schwant Schreckliches.
extra für dich hab ich mir Dropbox heruntergeladen und hier der link:
https://www.dropbox.com/sh/gi1u9o690yq4srj/AADdz_gLxVs5qTwstFaO5cpIa?dl=0
hoffe es klappt.
p.s. brauchst QT
edit hab noch ein bissisch aufgeräumt, sollte jetzt aber kleiner sein
-
win8789 schrieb:
Vielleicht fehlen win8789 da einfach nur die C++ Grundlagen?Was denkst du?
Ich denke ja. Und ich denke du hast ein "an" am Anfang dieses Satzes vergessen.

An was denke ich? Na z.B. daran wie das ganze mit Klassen, Konstruktoren, Destuktoren, Basisklassen etc. funktioniert. Also wie das alles ineinandergreift. Genau so was es mit lokalen Variablen und Destruktoren auf sich hat. Was dann erklärt warum behauptet wurde dass nen
std::vectormit new Erzeugen wohl nur selten Sinn macht (sinngemäss).Das ist aber richtig viel was es da zu wissen gibt, mehr man in einem Thread schnell mal zusammenfasst/erklärt. Also such/kauf/besorg dir ein gutes Buch. "The C++ Programming Language" von Stroustrup soll wohl recht gut sein *. Ansonsten gibt's hier ne Liste:
https://www.c-plusplus.net/forum/251551-full*: Beachte aber die Bewertungen auf Amazon. Die Softcover-Version scheint ein Fehldruck zu sein (fehlen angeblich 40 Seiten, an deren Stelle andere Seiten doppelt gedruckt wurden), und bei der Kindle-Edition scheint wohl die Formatierung der Codebeispiele nicht optimal zu funktionieren.
-
hustbaer schrieb:
An was denke ich? Na z.B. daran wie das ganze mit Klassen, Konstruktoren, Destuktoren, Basisklassen etc. funktioniert. Also wie das alles ineinandergreift. Genau so was es mit lokalen Variablen und Destruktoren auf sich hat. Was dann erklärt warum behauptet wurde dass nen
std::vectormit new Erzeugen wohl nur selten Sinn macht (sinngemäss).ok wär es dann besser einen rohen dynamischen array zu erstelllen?
p.s hast du dir meinen Quellcode angesehen? Eine kleine Rückmeldung wäre sehr nett.
-
ok hab jetzt mal versucht das ganze mit einem statischen vector zu machen.
Erbebis die Steine werden sofort nach den erseinen gelöscht. Ich denke mal, dass das an Qt liegt.Ich hab es so gemacht:
//im konstruktor: std::vector<item_group_item> item(1); //im anderen konstruktor std::vector<item_group_item> item(2); //im anderen std::vector<item_group_item> item(4); //im anderen, man könnte man das nicht anders machen std::vector<item_group_item> item(5); //als private variable in der Klasse private: std::vector<item_group_item> item;Wenn ich keinen fehler gemacht habe, muss ich wohl dynamsiche Objekte für die Spielsteine verwenden.
Oder um es anders zu Fragen, was ist jetzt nun der beste weg einen dynmamischen Array zu konstruieren. Soll ich eine einfachen Array verwenden:
//z.B. int * pointer = new int[irgenwas]; //später delete [] pointer;oder irgendeine Klasse verwenden.
-
win8789 schrieb:
Oder um es anders zu Fragen, was ist jetzt nun der beste weg einen dynmamischen Array zu konstruieren.
std::vector
//im konstruktor: std::vector<item_group_item> item(1); // ### Das macht eine lokale Variable im Konstruktor, die sofort wieder // ### zerstört wird wenn der Konstruktor fertig ist //im anderen konstruktor std::vector<item_group_item> item(2); // ### -- "" -- (...) //als private variable in der Klasse private: std::vector<item_group_item> item; // ### Das wäre die Membervariable, die du aber anscheinend nicht verwendest. // ### Die lokalen Variablen mit dem selben Namen "verdecken" die Membervariable.win8789 schrieb:
Wenn ich keinen fehler gemacht habe, muss ich wohl dynamsiche Objekte für die Spielsteine verwenden.
Hast du aber. Ich sag ja dir fehlen die Grundlagen. Was ja kein Problem ist, jeder hat mal angefangen. Nur irgendwann solltest du es lernen, und das wird sehr mühsam ohne gute Unterlagen. Kauf dir ein Buch.

Als Beispiel wie du nen vector als Membervariable anlegst und im Konstruktor dann Elemente einfügst:
class MeineKlasse { public: MeineKlasse(); void MachWas(); private: std::vector<MeinItem> m_items; }; // Variante 1 MeineKlasse::MeineKlasse() : m_items(123) // vector mit Grösse 123 initialisieren. Das erzeugt 123 Items mit dem Default-Konstruktor { } // Variante 2 MeineKlasse::MeineKlasse() // Wenn hier nix steht wird m_item mit dem Default-Konstruktor erzeugt, und ist dann erstmal leer { m_items.push_back(MeinItem("foo")); // Ein Item einfügen (wird in den vector rein kopiert) m_items.emplace_back("bar"); // Ein Item einfügen ohne dass es dabei kopiert werden muss // - es wird dabei direkt im vector erzeugt und mit "bar" initialisiert // ... } void MeineKlasse::MachWas() { // Alte Schreibweise, immer noch oft nützlich z.B. wenn man den Index i irgendwo braucht oder sowas for (size_t i = 0; i < m_items.size(); i++) // Alle Items durchgehen ... m_items[i].MachWas(); // ... und was machen // Moderne, kürzere schreibweise for (auto& item : m_items) // Alle Items durchgehen ... item.MachWas(); // ... und was machen }
-
hustbaer schrieb:
win8789 schrieb:
Wenn ich keinen fehler gemacht habe, muss ich wohl dynamsiche Objekte für die Spielsteine verwenden.
Hast du aber. Ich sag ja dir fehlen die Grundlagen. Was ja kein Problem ist, jeder hat mal angefangen. Nur irgendwann solltest du es lernen, und das wird sehr mühsam ohne gute Unterlagen. Kauf dir ein Buch.

Ok hab es nun verstanden. Wenn die Instanz selber dynamisch ist. So bleiben die Attribute selber so lange erhalten, wie es die Instanz gibt. Weshalb die Atribute einer Instanz fast immer statisch sein können.
danke, könntest du dir vielleicht noch den rest des Codes ansehen?
Übersehe hiebei am beseten den Konstruktor und desstroktor der Klasst item_group. Die überarbeite ich noch die tage
-
win8789 schrieb:
Weshalb die Atribute einer Instanz fast immer statisch sein können.
Ich hoffe du meinst hier mit statisch dass es halt ganz normale Member sind - nix Zeiger und so.
Weilstaticwürde nämlich ganz 'was anderes bedeuten.win8789 schrieb:
danke, könntest du dir vielleicht noch den rest des Codes ansehen?
Welcher Rest?