78 Stimmen

Prüfen, ob ein Iterator gültig ist

Gibt es eine Möglichkeit zu überprüfen, ob ein Iterator (ob es von einem Vektor, eine Liste, eine deque...) (noch) dereferenzierbar ist, d.h. nicht ungültig gemacht wurde?

Ich habe mit try - catch aber gibt es einen direkteren Weg, dies zu tun?

Beispiel: (was nicht funktioniert)

list<int> l;
for (i = 1; i<10; i++) {
    l.push_back(i * 10);
}

itd = l.begin();
itd++;
if (something) {
    l.erase(itd);
}

/* now, in other place.. check if it points to somewhere meaningful */
if (itd != l.end())
{
    //  blablabla
}

69voto

Jason Govig Punkte 1189

Ich nehme an, Sie meinen "ist ein Iterator gültig", dass er nicht aufgrund von Änderungen am Container (z. B. Einfügen/Löschen in/aus einem Vektor) ungültig geworden ist. In diesem Fall können Sie nicht feststellen, ob ein Iterator (sicher) dereferenzierbar ist.

27voto

avakar Punkte 31197

Wie jdehaan sagte, können Sie überprüfen, ob der Iterator nicht ungültig gemacht wurde und auf einen Container zeigt, indem Sie ihn mit container.end() .

Beachten Sie jedoch, dass, wenn der Iterator Einzigartig -- weil sie nicht initialisiert wurde oder nach einer Veränderung des Containers ungültig geworden ist (die Iteratoren eines Vektors werden ungültig, wenn man z.B. die Kapazität des Vektors erhöht) -- die einzige Operation, die man mit ihr durchführen darf, ist eine Zuweisung. Mit anderen Worten: Sie können nicht überprüfen, ob ein Iterator singulär ist oder nicht.

std::vector<int>::iterator iter = vec.begin();
vec.resize(vec.capacity() + 1);
// iter is now singular, you may only perform assignment on it,
// there is no way in general to determine whether it is singular or not

15voto

Terry Mahaffey Punkte 11439

Nicht tragbare Antwort: Ja - in Visual Studio

Die STL-Iteratoren von Visual Studio haben einen "Debugging"-Modus, der genau dies tut. Sie würden nicht wollen, um diese in Schiff-Builds zu aktivieren (es gibt Overhead), aber nützlich in geprüften Builds.

Lesen Sie darüber auf VC10 aquí (Dieses System kann sich bei jeder neuen Version ändern und tut es auch, daher sollten Sie die für Ihre Version spezifischen Dokumente lesen).

bearbeiten Außerdem sollte ich hinzufügen: Debug-Iteratoren in Visual Studio sind entworfen, um sofort explodieren, wenn Sie sie (statt undefiniertes Verhalten) verwenden; nicht zu "Abfragen" ihres Status zu ermöglichen.

9voto

jdehaan Punkte 19398

Normalerweise testet man es, indem man prüft, ob es sich von end() unterscheidet, wie

if (it != container.end())
{
   // then dereference
}

Darüber hinaus ist die Verwendung von Ausnahmebehandlungen zum Ersetzen von Logik in Bezug auf Design und Leistung schlecht. Ihre Frage ist sehr gut, und sie ist definitiv einen Austausch in Ihrem Code wert. Die Ausnahmebehandlung sollte, wie der Name schon sagt, nur für seltene unerwartete Probleme verwendet werden.

7voto

ChrisW Punkte 53239

Gibt es eine Möglichkeit zu überprüfen, ob ein Iterator (ob es von einem Vektor, eine Liste, eine deque ...) ist (noch) dereferencable, d.h. nicht ungültig gemacht worden?

Nein, die gibt es nicht. Stattdessen müssen Sie den Zugriff auf den Container kontrollieren, solange Ihr Iterator existiert, zum Beispiel:

  • Ihr Thread sollte den Container nicht verändern (den Iterator ungültig machen), solange er noch einen instanziierten Iterator für diesen Container verwendet

  • Wenn das Risiko besteht, dass andere Threads den Container verändern, während Ihr Thread iteriert, dann muss Ihr Thread, um dieses Szenario thread-sicher zu machen, eine Art Sperre für den Container erwerben (so dass er andere Threads daran hindert, den Container zu verändern, während er einen Iterator verwendet)

Umgehungen wie das Abfangen einer Ausnahme funktionieren nicht.

Dies ist ein spezieller Fall des allgemeineren Problems "Kann ich testen/ermitteln, ob ein Zeiger gültig ist?", dessen Antwort in der Regel lautet: "Nein, man kann nicht darauf testen: Stattdessen muss man alle Speicherzuweisungen und -löschungen verwalten, um wissen ob ein bestimmter Zeiger noch gültig ist".

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X