Iteratoren
-
Ich baue mir momentan einen eigenen Puffer bei welchem ist die std::list verwende und habe da ich eine, jedenfalls für mich, interessante Feststellung gemacht. Es kommt drauf an wann man einen Iterator initialisiert! Das ganze habe ich an einem kleinen Programm getestet und ich verstehe nicht, was der Unterschied sein soll:
#include <list> #include <iostream> int main() { std::list<int*> Liste; std::list<int*>::iterator I; // diese Zeile aktivieren //I = Liste.begin(); for( int j=1; j<10; j++) { int* i = new int; *i = j; Liste.push_back(i); } // und diese deaktivieren -> Programm funktioniert nicht mehr! I = Liste.begin(); for( int j=1; j<10; j++) { std::cout << **I << std::endl; I++; } return 0; }
-
Ich hab mal ein paar Kommentare hinzugefügt. Ich hoffe die helfen Dir.
DJohn
fabske schrieb:
... std::list<int*> Liste; std::list<int*>::iterator I; // diese Zeile aktivieren //I = Liste.begin(); // Hier ist die Liste leer. Was glaubst Du auf // welches Element der Iterator zeigt? for( int j=1; j<10; j++) { int* i = new int; *i = j; Liste.push_back(i); // Hier wird das erste Mal was in die Liste eingefügt. // Der Iterator I wird dabei nicht magisch verändert! } // und diese deaktivieren -> Programm funktioniert nicht mehr! I = Liste.begin(); //Hier gibt es tatsächlich ein erstes Element in der Liste. ... }
-
Vielen Dank für deine Erklärung! Hat mich auf ein Problem aufmerksam gemacht. Ich hab das gleiche mit einer deque probiert und da scheint es zu funktionieren! Jedenfalls reicht es für meine Zwecke.
#include <deque> #include <iostream> std::deque<int> data; int gibElement(std::deque<int>::iterator it) { if( it==data.end() ) return -1; // Ende! else return *it; }; int main(int argc, char** argv) { std::deque<int>::iterator it = data.begin(); data.push_back(1); data.push_back(2); std::cout << gibElement(it) << std::endl; it++; std::cout << gibElement(it) << std::endl; it++; data.pop_front(); data.pop_front(); data.push_back(3); data.push_back(4); std::cout << gibElement(it) << std::endl; it++; std::cout << gibElement(it) << std::endl; it++; std::cout << gibElement(it) << std::endl; return 0; }
-
Mach aus gibElement doch eine Templatefunktion und deine Iteratoren können ruhig const sein, da sie nicht dereferenzeirt und damit nicht verändert werden.
-
Kóyaánasqatsi schrieb:
Mach aus gibElement doch eine Templatefunktion und deine Iteratoren können ruhig const sein, da sie nicht dereferenzeirt und damit nicht verändert werden.
Was hat dereferenzieren mit verändern zu tun?
Und was soll er const machen? Aus dem iterator einen const_iterator? Oder ein const-Objekt übergeben?
So viel Freiheit in der Interpretationsmöglichkeit hat schon fast was mystisches...
-
fabske schrieb:
Ich hab das gleiche mit einer deque probiert und da scheint es zu funktionieren! Jedenfalls reicht es für meine Zwecke.
Dann hast Du einfach nur Glück gehabt!
fabske schrieb:
std::deque<int> data; std::deque<int>::iterator it = data.begin(); data.push_back(1); data.push_back(2); std::cout << gibElement(it) << std::endl; it++; std::cout << gibElement(it) << std::endl; it++;
deque<T>::push_back macht Iteratoren ggf ungültig. Dass das hier bei Dir funktioniert hat ist reines Glück. Verlassen kannst Du Dich nicht darauf!
list<T>::push_back macht Iteratoren nicht ungültig. Das ist eine besondere Garantie, die std::list macht.
Aber ein Iterator wie der, der von begin() bei einer leeren Sequenz zurückgegeben wird, zeigt auf kein Element! Solche Iteratoren darfst Du nicht dereferenzieren, inkrementieren oder dekrementieren!
read the f***ing manual
-
Alpha del Geipha schrieb:
Was hat dereferenzieren mit verändern zu tun?
Und was soll er const machen? Aus dem iterator einen const_iterator? Oder ein const-Objekt übergeben?
So viel Freiheit in der Interpretationsmöglichkeit hat schon fast was mystisches...Frag dich nicht, Koya tut noch gerne so, als haette er Ahnung.
-
senfer schrieb:
Aber ein Iterator wie der, der von begin() bei einer leeren Sequenz zurückgegeben wird, zeigt auf kein Element! Solche Iteratoren darfst Du nicht dereferenzieren, inkrementieren oder dekrementieren!
Gilt das nun allgemein und damit auch für list? Oder ist list, das ja eine besondere Garantie gibt, davon ausgenommen?
-
fabske schrieb:
Gilt das nun allgemein und damit auch für list? Oder ist list, das ja eine besondere Garantie gibt, davon ausgenommen?
Das gilt allgemein. Bei einem leeren Container, egal welchem, sind begin() und end() derselbe, nämlich der erste, letzte und einzige Iterator. begin() darf nicht dekrementiert werden, end() darf weder inkrementiert nochd ereferenziert werden. Damit gilt bei einem Iterator aus einem leeren Container alles zusammen.
list gibt da meines Wissens auch keine besonderen Garantien.