Destruktor: std::vector<obj*> ... sauber löschen

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Leverator
Beiträge: 32
Registriert: Mo Jan 30, 2012 9:28 pm
Wohnort: ::1

Destruktor: std::vector<obj*> ... sauber löschen

Beitrag von Leverator » So Mai 16, 2021 11:10 am

Moin zusammen,
mich treibt gerade ein Destruktor um, der geordnet in einem Vector gespeicherten Zeiger auf Objekte löschen soll.
Selbstverständlich sollen die Objekte selber auch mit delete(...) sauber aus dem Speicher entfernt werden (und selbstverständlich vorher deren Destruktoren aufgerufen werden).

Mein Ansatz:

Code: Alles auswählen

class klasseA {
  klasseA();
   ~klasseA();
  std::vector<obj*> objVec;
};

Code: Alles auswählen

klasseA::klasseA {
  objVec.push_back( new obj );
}

klasseA::~klasseA {
  for( std::vector<obj*>::iterator it=objVec.begin(); it != objVec.end(); ++it ) {
    delete( *it );
    objVec.erase( it );
  }
}
Problem: Speicherzugriffsfehler.

Ich habe nun mehrere Kombinationen aus delete und erase ausprobiert und konnte bisher noch nicht feststellen, dass es sauber funktioniert.
Nutze ich nur erase, dann wird zwar der Eintrag in dem Vector gelöscht - also: der Pointer entfernt - jedoch nicht das Objekt selbst aus dem Speicher.
Nutze ich nur delete, dann wird zwar das Objekt sauber über den Destruktor entfernt, jedoch bleibt der Eintrag in dem Vector erhalten (und wird ungültig: NULL).

Ich vermute das Problem in der for-Schleife, weil wir hier direkt auf die Größe der Liste einwirken, welche sich im Laufe der Loop ändert, womit evtl. die Schleife nicht fertig wird. Aber ich weiß es halt nicht, ob das stimmt und wie ich das ggfs. ändern könnte.

Wer weiß Rat?

Viele Grüße,
Lev

Leverator
Beiträge: 32
Registriert: Mo Jan 30, 2012 9:28 pm
Wohnort: ::1

Re: Destruktor: std::vector<obj*> ... sauber löschen

Beitrag von Leverator » So Mai 16, 2021 11:24 am

Ok...

... es hilft manchmal, das Problem aufzuschreiben, dann findet man oft selbst die Lösung.

Es funktioniert scheinbar mit folgendem Ansatz:

Code: Alles auswählen

klasseA::~klasseA {
  unsigned int size = objVec.size();
  
  for( unsigned int i=0; i<size; i++) {
    delete( *objVec.begin() );       // Das Objekt selbst löschen
    objVec.erase( objVec.begin() );  // Den Vector-Eintrag entfernen
  }
  
}
Viele Grüße,
Lev

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Destruktor: std::vector<obj*> ... sauber löschen

Beitrag von Xin » So Mai 16, 2021 9:48 pm

Leverator hat geschrieben:
So Mai 16, 2021 11:24 am
... es hilft manchmal, das Problem aufzuschreiben, dann findet man oft selbst die Lösung.
Sowas soll auch vorkommen.
Leverator hat geschrieben:
So Mai 16, 2021 11:24 am
Es funktioniert scheinbar mit folgendem Ansatz:

Code: Alles auswählen

klasseA::~klasseA {
  unsigned int size = objVec.size();
  
  for( unsigned int i=0; i<size; i++) {
    delete( *objVec.begin() );       // Das Objekt selbst löschen
    objVec.erase( objVec.begin() );  // Den Vector-Eintrag entfernen
  }
  
}
Erstmal danke, dass Du nicht nur schreibst "Problem gelöst.", sondern auch die Lösung mit reinreichst. :-D

Nur zum Mitgeben: Du löschst die Elemente, die Du im Vector referenzierst. Es ist für Dich also nicht wichtig, dass die Referenzen aus dem Vektor verschwinden und der Vektor neu angeordnet wird. Wenn Du das erste Element löschst, müssen ja alle anderen vorrücken. Hier wäre es also erstmal sinnvoll von hinten zu löschen, so dass das verschieben vermieden wird.

Aber der Vector wird ja ohne Konsequenzen durch den Destruktor sowieso gelöscht. Es reicht also alle Elemente, die Du referenzierst in einer beliebigen Reihenfolge zu löschen.

Code: Alles auswählen

klasseA::~klasseA {
  for( obj * value : objVec )
    delete value;
}
Der Vector mit allen (inzwischen ungültigen) Adressen existiert dann noch kurz weiter, wird dann aber beim Verlassen des Destruktors freigegeben.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten