2010-09-17 5 views
5

Sollten wir vor oder nach erase löschen. Mein Verständnis ist beides in Ordnung. Ist es richtig?Sollten wir vor oder nach dem Löschen für einen Zeiger im Vektor löschen?

Außerdem, werden wir in jedem Fall das Element nicht löschen wollen, während es gelöscht wird? Ich glaube es muss sein, sonst wird die erase gerne die Verantwortung übernehmen.

std::vector<foo*> bar; 
... 
for (vector<foo*>::iterator itr = bar.begin(); itr != bar.end(); itr++) 
{ 
    delete (*itr); //before OR 
    bar.erase(itr); 
    delete (*itr); //after??? 
} 
+0

meinst du 'std :: vector ' – sellibitze

+0

danke. korrigiert. – pierrotlefou

+0

Ich glaube, Sie haben 'iter ++' auch, sonst Schleife wird nicht beendet. – Naveen

Antwort

10

"itr" muss so verwendet werden;

for (vector<foo*>::iterator itr = bar.begin(); itr != bar.end();) 
{ 
    delete (*itr); 
    itr = bar.erase(itr); 
} 

Allerdings würde ich lieber zuerst alle Elemente löschen und dann den Vektor löschen;

for (vector<foo*>::iterator itr = bar.begin(); itr != bar.end(); ++itr) 
    delete (*itr); 
bar.clear(); 
+1

+1, würde ich auch für die zweite Version entscheiden: so würde ich nicht alle diese Verschiebungen von Elementen innerhalb des Vektors haben. Wenn zumindest eine Schleife mit Löschen verwendet wird, wäre eine Rückwärtsiteration besser geeignet. –

+0

Ich stimme zu, aber ich bin mir nicht sicher, ob Vector :: Erase mit einem Reverse_iterator kompatibel ist (zu müde, um es durch zu denken) –

+0

Sie sollten die bevorzugte Lösung verwenden. Es ist ** O (n) ** im Gegensatz zu ** O (n^2) **. – kevlar

4

Die Verwendung eines Iterators zum Löschen eines Elements macht den Iterator ungültig. Sie sollten das Objekt löschen, bevor es gelöscht wird.

Sie sollten auch den Rückgabewert von Erase für Ihre nächste Schleifeniteration verwenden.

+0

gute Kommentare im Allgemeinen, aber können Sie uns sagen, was der Grund hinter "Sie sollten das Element löschen, bevor es gelöscht wird". Ich verstehe nicht, warum das so sein sollte. In der Tat würde ich denken, dass das Gegenteil sicherer wäre (zB in Multithreading-Code). Der Nachteil ist, dass Sie den Wert des Zeigers in einem temporären behalten müssen, bevor er Löschen anruft, oder Sie werden nicht in der Lage sein, es zu löschen. Ich sehe es einen großen Vorteil nicht so nicht würde es aber die Weise Sie empfehlen formulierte deine Antwort es sieht aus wie Löschen vor ist der einzige Weg. – n1ckp

+0

@ n1ck: Er fragte zwischen zwei Varianten (d. H. Vorher oder nachher). Ich habe nur die Frage angesprochen. Natürlich können Sie den Zeiger auf ein temporäres verschieben, aber das Löschen an Ort und Stelle funktioniert auch für die meisten Anwendungen. – Paul

+0

Harvey: Klar, ich habe gerade gesagt, dass deine Formulierung vielleicht nicht die beste ist, da sie andeutet, dass es die einzige Möglichkeit ist. Ich denke, der Leser sollte verstehen können, aber ich wollte nur ganz klar sein, das ist alles. – n1ckp

1

Durch Ausführen einer erase wird der vector Iterator ungültig gemacht. So ruft *iter undefiniertes Verhalten auf. Daher müssen Sie die delete nach der erase tun. Auch können Sie nicht die erase Elemente von einem vector während es durchlaufen (aus dem gleichen Grund, iter wird ungültig, so iter++ ist ungültig). In diesem Fall können Sie den erase Aufruf innerhalb der Schleife entfernen und clear des Vektors außerhalb der Schleife tun.

2

Die Art des Vektors, das gesamte Array erste Element bewirkt, dass das Löschen nach vorne zu verschieben, um diesen Vorgang zu verringern versuchen folgenden: Übrigens

std::vector<foo*> v1; 
//... 
while(!v1.empty()) 
{ 
    delete v1.back(); 
    v1.pop_back(); 
} 

- diese Methode keine Iteratoren nicht ungültig machen (nur bei gelöschten Artikeln)

3

Außerdem, werden wir auf keinen Fall das Element löschen wollen, während es gelöscht wird?

Wie könnte der Vektor möglicherweise wissen, ob jemand anderes die Objekte benötigt, auf die er zeigt? Wie konnte es überhaupt wissen, dass die Spitzen auf dem Haufen gelagert sind? Es ist durchaus möglich, Zeiger auf statische oder automatische Objekte in dem Vektor zu haben oder sogar Zeiger zu hängen.

C++ 0x können Sie zum Ausdruck bringen, dass der Vektor die pointees besitzen sollte:

std::vector<std::unique_ptr<foo>> vec; 

Jetzt manuell nichts löschen. Durch Löschen der eindeutigen Zeiger werden ihre jeweiligen Zeiger ebenfalls gelöscht. Container mit nativen Zeigern sind im modernen C++ sehr selten. Wenn Sie keinen C++ 0x-Compiler haben, können Sie statt dessen std::vector<boost::shared_ptr<foo> > oder boost::ptr_vector<foo> verwenden. Moderne Compiler liefern shared_ptr im Namespace std::tr1 oder std auch wenn Sie #include <memory>.