Array einer eigenen Klasse dynamisch erweitern ->Frage zum Destruktor [GELÖST]
-
butterbemme schrieb:
Und die addPerson Funktion schaut so aus:
void Personenliste::addPerson(Person per){ p[anzahl]=per; anzahl++; if(anzahl==gr){ Person* neu=new Person[gr=gr+1]; ~Personenliste(); p=neu; } cout << "Person eingefuegt" << endl; }Auweia!
perbitte per ref-auf-const übergeben. Die Puffergröße sollte sich verdoppeln und nicht immer nur ein Element größer werden. Damit erreichst Du dann beim wiederholten addPerson amortisiert konstante Laufzeit pro Aufruf statt eine Laufzeit, die abhängig von der Größe des Puffers ist. Destruktor ruft man (so gut wie) nie selbst auf! Jedenfalls nicht hier! Die alten Personen werden nirgenswo in den neuen Puffer kopiert. Du verletzt die Dreierregel und bekommst murksiges Verhalten, wenn Du so ein Personenliste Objekt kopierst.class Personenlistekannst du komplett gegenstd::vector<Person>eintauschen.std::vectorhat all diese genannten Probleme nicht.
-
Also std::vector is mir bekannt.
Ich versuch mich grade in selbstdefinierte Klassen einzuarbeiten und will ein bisschen mit new und delete rumspielen, deswegen mein etwas umständlicher Code.
Ist also sozusagen eine Übung.@Belli: du meinst ich solle nur "delete[] p" benutzen. Aber genau das und zwar nur das, steht ja auch in meinem selbstdefinierten Destruktor ~Personenliste().
Wo ist dann also der Unterschied? Oder wird da implizit noch etwas anderes im Hintergrund gemacht.krümelkacker schrieb:
... Die alten Personen werden nirgenswo in den neuen Puffer kopiert. Du verletzt die Dreierregel und bekommst murksiges Verhalten, wenn Du so ein Personenliste Objekt kopierst...
Jo da hast du Recht. Um die Dreierregel hab ich mich noch nicht gekümmert, und auch das Kopieren der Personen aus dem alten Speicherbereich fehlt noch.
Dann lass ich wohl vorerst die Finger von selbstdefinierten Destruktor.
Aber zu guter Letzt würd mich noch interessieren warum der direkte Destruktoraufruf (~Personenliste()) in der Funktion "addPerson()" nicht funktioniert hat.
Ich bekomm da immerUnärer Operator '~': 'Personenliste' definiert diesen Operator oder eine Konvertierung in einen für den vordefinierten Operator geeigneten Typ nicht
Muss ich diesen Operator erst für mein Vorhaben extra definieren. Dachte eigentlich Destruktoren haben diese Form und werden dann auch so aufgerufen
-
void Personenliste::addPerson( Person& const person ) { if ( anzahl >= gr ) { Person* tmp = 0; size_t neuAnzahl = gr + gr/ 2; if ( neuAnzahl < gr + 1 && gr + 1 > gr ) { neuAnzahl = gr + 1; } else throw std::bad_alloc( "Speicher voll" ); // :) Person* tmp = new ( nothrow ) Person[ neuAnzahl ]; if ( tmp == 0 ) throw std::bad_alloc(); memcpy( tmp, p, min( gr, neuAnzahl ) * sizeof ( Person ) ); delete[] p; p = tmp; gr = newAnzahl; } p[ anzahl ] = person; ++anzahl; }vorausgesetzt Person ist POD..
-
Nimm statt
memcpylieberstd::copy, das funktioniert auch mit non-POD Typen und ist etwas handlicher imho.void Personenliste::add_person( const Person& p ) { if( Anzahl >= gr ) { size_t NewSize = gr * 2; Person* buffer = new Person*[NewSize]; std::copy( p, p + gr, buffer ); delete[] p; p = buffer; gr = NewSize; } p[Anzahl] = person; ++anzahl; }
-
butterbemme schrieb:
[...]
@Belli: du meinst ich solle nur "delete[] p" benutzen. Aber genau das und zwar nur das, steht ja auch in meinem selbstdefinierten Destruktor ~Personenliste().
Wo ist dann also der Unterschied? Oder wird da implizit noch etwas anderes im Hintergrund gemacht.[...]
Dachte eigentlich Destruktoren haben diese Form und werden dann auch so aufgerufen
Ja, da wird - wie hier auch schon jemand schrieb - Dein Objekt zerstört.
Destruktoren haben diese Form, aber wie auch schon jemand schrieb, sie werden nicht explizit aufgerufen.{ objekt a; }// hier wird wegen des Verlassens des Scopes der Destruktor von a implizit aufgerufen. objekt *b = new b(); // hier muss es natürlich: objekt *b = new objekt(); heißen, :) delete b; // hier wird von delete der Destruktor von b implizit aufgerufenAnders solltest Du bis auf Weiteres Destruktoren nicht aufrufen.
-
Okay, ich denke ich habs soweit verstanden.
Danke für eure Hilfe.
-
hey arbeite dich erstmal durch ein klassen tut... so kommste nicht weit ^^
hier noch ne regel falls du weiter auf dem heap arbeiten möchtest
definierst du einen dieser drei selbst:
destructor
copy constructor
zuweisungs operatormusst du in der regel alle selbst schreiben, aber naja kommt noch ;P
-
Üblicherweise ruft man einen Dtor nur dann explizit auf, wenn das Element mit einer Form von placement-new erzeugt wurde.
-
DocShoe schrieb:
Nimm statt
memcpylieberstd::copy, das funktioniert auch mit non-POD Typen und ist etwas handlicher imho.void Personenliste::add_person( const Person& p ) { if( Anzahl >= gr ) { size_t NewSize = gr * 2; Person* buffer = new Person*[NewSize]; std::copy( p, p + gr, buffer ); delete[] p; p = buffer; gr = NewSize; } p[Anzahl] = person; ++anzahl; }Was ist mit
gr == 0?
Warum wirdnew[]mit dem falschen Typ benutzt?
Was ist, wenncopywirft?
Was sindanzahlundAnzahl?
Warum nicht gleich vernünftig mit Allocator?
-
Ich bin mal so frei und werde den Thread als "gelöst" markieren. Wenns noch Unstimmigkeiten unter den einzelnen Postern gibt, können die den Thread ja trotzdem weiterfürhen