2015-02-25 7 views
20
#include <vector> 
#include <algorithm> 

using namespace std; 

int main() { 
    vector<int> a = {1,2,3,7,1,5,4}; 
    vector<int> b = {6,7,4,3,3,1,7}; 
    a.erase(remove(a.begin(),a.end(),a[0]),a.end()); 
    b.erase(remove(b.begin(),b.end(),b[0]),b.end()); 

    return 1; 
} 

Für dieses spezielle Beispiel für konkretes Beispiel arbeiten, mein GNU gdb Ubuntu 7.7.1 besagt, dass bei Rückkehr 1 Zeile: a = { 2,3,7,1,5,4}, was nicht erwartet wird (löscht nur eine 1), und b = {7,4,3,3,1}, was nicht erwartet wird.std :: Lösch- und std :: entfernen Kombination bestimmtes Element nicht gelöscht

Meine Erwartung ist b sollte a = 2,3,7,5,4 und b = 7,4,3,3,1,7 sein.

Was passiert hier?

+2

Würdest du nicht erwarten, dass der erste alle 1s entfernt und "{2,3,7,5,4};" ergibt? – juanchopanza

+4

Warum ist das erste Ergebnis wie erwartet? Sollte es nicht "2,3,7,5,4" sein (beide '1's werden entfernt)? Ich glaube, Sie verletzen eine Vorbedingung, indem Sie einen Verweis auf ein Mitglied des "Vektors" übergeben, über das Sie gerade iterieren. Beide Zeilen können durch eine Kopie fixiert werden - '+ a [0]' und '+ b [0]' – Praetorian

+1

Dies ist eigentlich ziemlich nah an einem SSCCE. Es benötigt nur den Ausgabecode. –

Antwort

19

Die Erklärung von std::remove() sieht aus wie

template <class ForwardIterator, class T> 
    ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val); 

Beachten Sie, dass der letzte Parameter eine Referenz. Somit wird nach der Kompilierung die Adresse des angegebenen Elements übergeben.

von remove(a.begin(), a.end(), a[0]), etwas um die Adresse zu dem 0-ten Element der a anzeigt eingeleitet. Wenn remove() ausgeführt wird, sobald das 0-te Element gehandhabt wird, wird der Wert durch den Verweis übergeben in geändert hingewiesen, die zu dem unerwarteten Ergebnis führt.

Um das erwartete Ergebnis zu erhalten, erstellen Sie eine Kopie, bevor Sie std::remove() anrufen.

int toberemoved = a[0]; 
a.erase(remove(a.begin(),a.end(),toberemoved),a.end()); 
+5

Das war meine erste Reaktion auch. Aber der Standard stellt diese Anforderung nicht. Das bedeutet, dass die Implementierung von "std :: remove" die notwendigen Vorkehrungen treffen muss. Wenn er das beschriebene Problem hat, ist das ein Fehler in der Bibliothek. Oder vielleicht im Standard, weil vielleicht die Absicht war, dass dies nicht erforderlich sein sollte, um zu arbeiten. –

+0

@StefanoSanfilippo Es funktioniert gut. – juanchopanza

+4

@StefanoSanfilippo Ihr Link zeigt, dass es funktioniert. – juanchopanza

Verwandte Themen