Frage

Angenommen, ich habe eine std::vector<Obj *> objs (aus Performance-Gründen habe ich Zeiger nicht unbedingt Objs).

ich bevölkern es mit obj.push_back(new Obj(...)); wiederholt.

Nachdem ich fertig bin, habe ich die zurückgeschobenen Elemente delete. Eine Möglichkeit, dies zu tun:

for (std::vector<Obj *>::iterator it = objs.begin(); it != objs.end(); ++it) {
    delete *it;
}

Aber ich interessiere mich, wenn ich for_each Algorithmus verwenden können, das Gleiche zu tun:

#include <algorithm>
...
for_each(objs.begin(), objs.end(), delete);

Was denken Sie?

War es hilfreich?

Lösung

Ihr Problem ist, dass delete ist keine Funktion, sondern ein Schlüsselwort und als solche können Sie es nicht die Adresse.

In C ++ 0x, wird es eine std::default_delete Klasse (von std::unique_ptr verwendet), die Sie verwenden können, oder - wie jeder sagen - ein Schreiben selbst trivial sein würde (der Standard ein wirft auch einen Compiler-Fehler, wenn Sie versuchen, einen unvollständigen Typen löschen).

#include <vector>
#include <algorithm>
#include <memory>

int main()
{
    std::vector<int*> vec;
    std::for_each(vec.begin(), vec.end(), std::default_delete<int>());
}

Andere Tipps

Ja, aber Sie müssen einen Funktor:

struct delete_ptr
{
    template <typename T>
    void operator()(T* pPtr)
    {
        delete pPtr;
    }
};

std::for_each(objs.begin(), objs.end(), delete_ptr());

In C ++ 0x, Lambda-Hilfe Sie machen functors an Ort und Stelle:

std::for_each(objs.begin(), objs.end(), [](Obj* pPtr){ delete pPtr; });

Dies ist jedoch gefährlich, angesichts der Ausnahmen.

Während Sie können dies tun ( GMan hat eine Lösung ), gezeigt Behälter mit nacktem Zeiger auf Besitz Mangel an Mitteln, ist eine strong Code Geruch. Zum Beispiel in diesem Code:

  void foo()
  {
    std::vector<Obj *> bar;
    fill(bar);
    use(bar);
    std::for_each(objs.begin(), objs.end(), delete_ptr()); // as GMan suggests
  }

Wenn use() wirft, werden Sie Objekte auslaufen.

So ist es besser, intelligente Zeiger für diese verwenden:

std::vector< std::shared_ptr<Obj> > bar;

Nicht gerade; for_each erfordert eine Funktion oder ein Objekt, das mit () aufgerufen werden kann, und delete ist weder eine Funktion noch ein Objekt. Sie werden es in einer Funktion (oder Funktionsobjekt), vielleicht wie müssen einpacken:

struct Deleter
{
    void operator()(Obj* obj) {delete obj;}
};

std::for_each(objs.begin(), objs.end(), Deleter());

Aber Sie sollten sehr vorsichtig Verwaltung Objektlebensdauern mit rohen Zeiger sein, vor allem, wenn man sie um vorbei sind. Sie werden merken müssen, um sie zu löschen, wenn sie aus dem vector löschen oder neu zuweisen sie, oder wenn Sie die vector löschen, oder wenn eine Ausnahme, Bruch oder Funktion Rückkehr könnte bewirken, dass der Vektor zerstört werden. Im Allgemeinen ist es immer besser, die Verantwortung des Ressourcenmanagements und die Ressourcennutzung zu trennen.

Sie würden besser sein, mit einem Vektor von Objekten aus, es sei denn, Obj eine polymorphe Basisklasse ist, oder die Objekte wirklich groß oder kompliziert genug, dass sie zu kopieren einen spürbaren Einfluss auf die Leistung haben. Wenn das der Fall ist (und Sie haben profilierte er sicher sein, dass es der Fall ist), sollten Sie einen Vektor von Smart Pointer betrachten (shared_ptr oder unique_ptr, wenn Ihr Compiler unterstützt) oder Erhöhung des ptr_vector.

Ankommen in der Gewohnheit, mit Hilfe der automatischen Ressourcenmanagement Klassen werden Ihnen in Zukunft eine Menge Kopfschmerzen speichern.

Anstatt zu versuchen, das Löschen Problem zu lösen, können Sie es vollständig weggehen von shared_ptrs in dem Vektor zu speichern, oder durch Auftrieb des ptr_vector (siehe http://www.boost.org/doc/libs/1_39_0/libs/ptr_container/doc/tutorial.html ).

muss for_each einen Funktionszeiger oder ein Funktionsobjekt. Für Speicherfreigabe könnten Sie versuchen &::operator delete, die die Adresse der Funktion, die Speicher freigibt nehmen würde. Wenn Sie jedoch die Lösch Anweisung der Compiler ruft den Destruktor verwenden vor dem Aufruf operator delete(void*) so Bereinigung eigentlich nicht Teil der operator delete(void*) Funktion ist.

Verwenden Sie einen Funktor ala GMan Antwort.

Ja. Füllen Sie es mit Smart-Pointer und Verwendung vector.clear () ist der einfachste Weg.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top