2013-04-23 15 views
6

Der folgende Code funktioniert wie erwartet (der Test besteht), aber ich frage mich, ob die Arbeit mit Iteratoren auf diese Weise als eine schlechte Praxis in C++ oder wenn es in Ordnung ist.Anfügen eines std :: vector mit seinen eigenen Elementen mit Iteratoren

Vielleicht ist dies spezifisch für std::vector und andere Sammlungen verhalten sich anders und Best Practices variieren zwischen Sammlungen (oder sogar ihre Implementierungen)?

Es ist sicherlich nicht in anderen Sprachen in Ordnung und die meiste Zeit ändern eine Sammlung Iteratoren ungültig und Ausnahmen auslösen.

BOOST_AUTO_TEST_CASE (ReverseIteratorExample) { 
    std::vector<int> myvector; 
    for(int i = 0; i < 5; i++) 
    { 
     myvector.push_back(i); 
    } 

    // is this generally a bad idea to change the vector while iterating? 
    // is it okay in this specific case? 
    myvector.reserve(myvector.size() + myvector.size() - 2); 
    myvector.insert(myvector.end(), myvector.rbegin() + 1, myvector.rend() -1); 

    int resultset [8] = { 0,1,2,3,4,3,2,1 }; 
    std::vector<int> resultVector(resultset, resultset + sizeof(resultset)/sizeof(resultset[0])); 
    BOOST_CHECK_EQUAL_COLLECTIONS(myvector.begin(), myvector.end(), resultVector.begin(), resultVector.end()); 
} 

Zusammengefasst Fragen:

  1. Ist dies in der Regel eine schlechte Idee, den Vektor während Iterieren zu ändern?
  2. Ist es in diesem speziellen Fall in Ordnung?
  3. Ist dies spezifisch für std::vector und andere Sammlungen verhalten sich anders?
  4. Unterscheiden sich Best Practices zwischen Sammlungen (oder sogar deren Implementierungen)?
+0

Es ist wirklich interessant, so Frage und ihre Antworten, auf die ich immer beziehen, wenn im Zweifel: http://stackoverflow.com/questions/4114503/rules-for-iterator-invalidation Es listet Standard C++ Container und der Fall, in dem Iteratoren ungültig oder noch gültig sind. (die Ihre Punkte 3 und 4 beantwortet.) –

+0

In Bezug auf # 4: verwenden Sie 'std :: list' – TemplateRex

Antwort

12

Dies ist kein gültiger Code. Die Standard-Definition von Operationen auf Sequenzcontainer Zustände ([email protected]):

a.insert (p, i, j) - [...] vor: i und j nicht Iteratoren in a.

Ihr Code ruft also undefiniertes Verhalten auf, weil es die Voraussetzung für die Operation insert verletzt.

Wenn stattdessen insert zu verwenden, schrieb Sie eine myvector.rbegin() + 1-myvector.rend() -1 Iterieren Schleife und rief push_back auf alle Werte, würde der Code gültig sein: Das ist, weil push_back nur Vektor Iteratoren ungültig, wenn eine Neuzuweisung erforderlich ist, und auf Ihren Anruf reserve stellt sicher, dass dies nicht der Fall ist.

Obwohl es in einigen Fällen Fälle gibt, in denen das Ändern eines Containers während des Iterierens in Ordnung ist (z. B. die oben beschriebene Schleife), müssen Sie sicherstellen, dass Ihre Iteratoren nicht ungültig gemacht werden. Wenn dies passiert, ist dies für jeden Container spezifisch.

+0

für Container spezifische Iterator-Validierungsregeln siehe diese [Frage] (http://stackoverflow.com/questions/6438086/iterator -invalidationsregeln? lq = 1) – TemplateRex

+0

Danke für deine Antwort. Schade, dass es scheint zu funktionieren. Ich füge es meiner Liste der Dinge hinzu, die ich an C++ hasse. – tobsen

Verwandte Themen