Iteratoren bei std::list
-
Hallo,
Ich möchte mir gerne mittels Iteratoren einen Bereich einer Liste merken, so daß ich später über diese Iteratoren auf genau die selben Elemente der Liste zugreifen kann.
Zwischendurch möchte ich aber außerhalb dieses Bereichs Elemente hinzufügen oder löschen können. Das funktioniert auch, solange ich nicht gerade genau hinter dem gemerkten Bereich etwas an der Liste ändere.Ein bißchen Code sagt mehr als tausend Worte:
#include <iostream> #include <list> int main() { std::list<int> l; l.push_back(5); l.push_back(23); std::list<int>::iterator a = l.begin(); std::list<int>::iterator b = l.end(); // ... l.insert(l.end(), 42); // ... for (std::list<int>::iterator i = a; i != b; ++i) { std::cout << *i << std::endl; // upps... da war's einer zu viel... } return 0; }Erreichen möchte ich, daß nur die 5 und die 23 ausgegeben werden, aber nicht die 42. Wie könnte man dieses Problem auf halbwegs elegante Weise lösen?
-
weil end() immer end() ist. den end-iteartor merken bringt nicht viel... du musst dir einen anderen iterator merken.
-
Um was gehts den? Den Wert, oder die Position darf nicht ausgegeben werden?
Wenn du die Position haben willst, dann kannst du dir den Abstand merken.
int pos = l.insert(l.end(), 42) - l.begin ();Und dann einfach diese Position überspringen.
Wenn der Wert nicht ausgegeben werden darft, überprüfst du das hald einfach in der Schlaufe.
-
Shade Of Mine schrieb:
weil end() immer end() ist. den end-iteartor merken bringt nicht viel... du musst dir einen anderen iterator merken.
Ok, das ist soweit klar...
Naja, wenn ich vor dem insert() ein --b mache, und danach wieder ein ++b, dann hätte ich das Ziel eigentlich erreicht. Nur finde ich das a) reichlich häßlich, und b) wird das ausgesprochen unübersichtlich, da das insert() in meinem konkreten Fall in einer anderen Funktion steht, die auch wiederum von mehreren Stellen aus aufgerufen werden kann...
Ich hätte halt gehofft, daß es da irgendwie eine schönere Lösung gibt...
drakon schrieb:
Wenn du die Position haben willst, dann kannst du dir den Abstand merken.
int pos = l.insert(l.end(), 42) - l.begin ();Leider geht das so nicht, da ich bei einer Liste ja nur bidirektionale Iteratoren habe. Prinzipiell könnte ich natürlich auch den Abstand herausbekommen, das scheint mir aber schon allein aus Performancegründen keine besonders gute Idee zu sein.
-
Es gibt std::distance um den Abstand zwischen zwei Iteratoren herauszufinden. Allerdings ist die Laufzeit bei Bidirektionalen Iteratoren wirklich linear, also nicht so günstig.
Ich sehe grundsätzlich zwei andere Arten:
1. Du nimmst den Start-Iterator und den End-Iterator. Bevor du diese speicherst, verringerst du den End-Iterator um eins. Bei der Verwendung, vergrösserst du ihn wieder um eins. Das ist ein einmaliges -- und einmaliges ++. Dabei muss aber gewährleistet sein, dass sich etwas in diesem Bereich befindet!
2. Du erstellst dir eine Kopie von dem Bereich und speicherst es in einer anderen Liste, welche du dann später wieder verwendest.Grüssli