2016-03-31 5 views
0

Ich habe diese Funktion erstellt, die mit Vektoren, verknüpften Listen und doppelt verknüpften Listen funktioniert. Die Funktion nimmt einen Wert und sucht im Container danach. Wenn sich der Wert im Container befindet, fügt die Funktion den Wert direkt neben dem bereits vorhandenen Wert ein. Also, wenn val=2 dann {3,2,5} wird {3,2,2,5} werden. Wenn der Wert im Container nicht vorhanden ist, wird er stattdessen auf der Rückseite hinzugefügt.EXC Schlechter Zugriff mit Iteratoren

Ich schrieb diese Funktion mit Iteratoren. Es funktioniert gut mit einem Vektor, aber wenn ich versuche, es mit einer Liste oder doppelt verknüpften Liste auszuführen, erhalte ich einen Exc Bad Access-Fehler in der Zeile if (*it==val). Ich sehe nicht, was ich falsch gemacht habe.

Edit: Vielen Dank an alle! Ihr Vorschlag, die if Erklärung zu ändern, hat perfekt funktioniert!

+0

Wenn das 'val' nicht gefunden wird, dann leitet die' if' Bedingung das Endelement ab, das zu UB führt. – Mahesh

Antwort

2

ändern

if (*it == val) 

zu:

if (it != x.end()) 

Wenn val nicht im Container gefunden wird, endet die Schleife bei it == x.end(). Das zeigt über das Ende des Arrays hinaus, so dass eine indirekte Ausrichtung zu einem undefinierten Verhalten führt.

0

Jemand korrigiert mich, wenn ich falsch liege, aber ich glaube, Ihr Fehler kommt von der Tatsache, dass wenn Ihr Iterator das Ende der Liste erreicht, zeigt es tatsächlich auf die Adresse nach dem letzten Bit der Liste im Speicher, die möglicherweise oder möglicherweise nicht initialisiert und im Umfang, die Ihr Programm zu Fehler führt.

2

Wenn der Wert noch nicht vorhanden ist, ist it gleich end(), wenn die Schleife beendet ist, und Sie können die end() nicht dereferenzieren. Sie müssen stattdessen if (*it == val)-if (it != x.end()) ändern:

//if (*it == val){ 
if (it != x.end()){ 
    x.insert(it, val); 
} 

Alternativ kann, da Sie nur einen Wert einfügen, wenn Sie val finden, dann können Sie die insert() tun und die Funktion sofort verlassen, und dann push_back() nur, wenn die Schleife erreicht das Ende des Behälters:

template <class Container, class T> 
void insertNextTo(Container &x, const T &val) { 
    typename Container::iterator it = x.begin(); 
    while (it != x.end()) { 
     if (*it == val) { 
      x.insert(it, val); 
      return; 
     } 
     ++it; 
    } 
    x.push_back(val); 
} 

In diesem Fall Sie den Code unter Verwendung std::find() anstelle einer manuellen Schleife vereinfachen können:

#include <algorithm> 

template <class Container, class T> 
void insertNextTo(Container &x, const T &val) { 
    typename Container::iterator it = std::find(x.begin(), x.end(), val); 
    if (it != x.end()) { 
     x.insert(it, val); 
    } else { 
     x.push_back(val); 
    } 
} 

Oder auch dies, da es zu insert() mit dem end() Iterator sicher ist, ist es das Gleiche wie push_back():

template <class Container, class T> 
void insertNextTo(Container &x, const T &val) { 
    typename Container::iterator it = std::find(x.begin(), x.end(), val); 
    x.insert(it, val); 
}