Seite 1 von 1

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

Verfasst: So Mai 16, 2021 11:10 am
von Leverator
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

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

Verfasst: So Mai 16, 2021 11:24 am
von Leverator
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

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

Verfasst: So Mai 16, 2021 9:48 pm
von Xin
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.