Random Access Liste, Iterator



  • Hallo zusammen,

    ich bin der Neue hier.

    Folgende Situation:

    #include <iostream>
    #include <list>
    
    using namespace std;
    
    class MyClass
    {
        int id;
        char whatever;
    };
    
    int main()
    {
        list<MyClass> fooList;
        list<MyClass>::iterator it;
    
        MyClass listElement;
    
        fooList.insert(it=fooList.begin(), listElement);
    
        return 0;
    }
    

    Dieses Programm sollte an den Anfang der Liste 'fooList' das Element 'listElement' einfügen. Wie stell ich es an, dass ich ein Element an einer bestimmten Position in der Liste einfüge?
    Ich kann ja den Iterator so

    it=fooList.begin()++;
    

    oder so

    it=fooList.begin()--;
    

    verschieben.
    Aber so was kompiliert nicht:

    it=fooList.begin()+5;
    

    Und wenn ich einen Iterator auf Position 5 schiebe und insert() ausführe, aber noch keine Listenelemente existieren, werden dann die vorherigen 4 Positionen aufgefüllt (aber mit was)?

    Ich werd noch ein bisschen experimentieren...

    MfG Ernesto



  • z.bsp.:

    std::list<int> foo;
    for(int i(0), e(20); i != e; ++i)
      foo.push_back(i);
    
    std::list<int>::iterator iter = foo.begin();
    std::advance(iter, 5);
    
    foo.insert(iter, 0);
    

    bb



  • Ernesto schrieb:

    Ich kann ja den Iterator so

    it=fooList.begin()++;
    

    oder so

    it=fooList.begin()--;
    

    verschieben.
    Aber so was kompiliert nicht:

    it=fooList.begin()+5;
    

    Schau dir nochmal an, was diese Postfix-Operatoren ++ und -- machen. Sie liefern nämlich den alten Iterator-Wert zurück. Der temporäre Iterator, den du veränderst, macht einfach den Verschwindibus beim Semikolon. Natürlich klappt +5 hier nicht, da std::list dir keinen Random-Access-Iterator bietet.

    Ernesto schrieb:

    Und wenn ich einen Iterator auf Position 5 schiebe und insert() ausführe, aber noch keine Listenelemente existieren, werden dann die vorherigen 4 Positionen aufgefüllt (aber mit was)?

    Ich werd noch ein bisschen experimentieren...

    Wie wär's stattdessen mit RTFM? Gibt so einige Referenzen ... online ... und auch in Buchform.



  • c-plusplus.net Reference schrieb:

    std::list::insert
    Insert elements
    The list container is extended by inserting new elements before the element at position.

    int main()
    {
        list<int> fooList{5, 6, 7, 8, 9, 0, 1, 2, 3, 4}; //c++11, sonst push_back o.ä.
        list<int> bar{200, 300, 400, 500};
    
        fooList.push_front(10); //Einfach vorne ein element einfügen
    
        auto it(begin(fooList)); //iterator auf das erste Element in der Liste
    
        fooList.insert(it, 200); //200 vor position it einfügen
        fooList.insert(it, {200, 300, 400, 500}); //c++11 direkt eine ganze range einfügen
        fooList.insert(it, begin(bar), end(bar)); //oder eben so ohne c++11
    
        for(auto const &it : fooList)
            cout << it << "\n"; //ausgeben
    }
    

    Analog sollte das mit deinen Objekten funktionieren.



  • Nachtrag: Entschuldige, ich verwende diverse C++11 Features, arbeite selbst grad ein Buch dazu durch. Hier nochmal ohne C++11:

    list<int> fooList, bar;
    
        for (unsigned i(0); i<20; ++i)
            fooList.push_back(i*2);
    
        for (unsigned i(0); i<5; ++i)
            bar.push_back(i*100);
    
        fooList.push_front(10); //Einfach vorne ein element einfügen
    
        list<int>::iterator const it(fooList.begin()); //iterator auf das erste Element in der Liste
    
        fooList.insert(it, 200); //200 vor position it einfügen
        fooList.insert(it, bar.begin(), bar.end());
    
        for(list<int>::const_iterator it(fooList.begin()); it != fooList.end(); ++it)
            cout << *it << "\n"; //ausgeben
    


  • Danke für eure Hilfe.

    Die advance() Funktion gefällt mir ganz gut. Mir ist in dem Zusammenhang noch ein nettes Feature aufgefallen: Wenn die Position auf die ich zugreifen will größer ist als die Länge der Liste, wird die Liste einfach nochmal durchgezählt. Ob das in der Anwendung Sinn macht, sei mal außer acht gelassen 😉
    Im Gegensatz zu std::vector, wo in dem Fall einfach ein Segfault rauskommt. Das liegt sicherlich an dem, ebenfalls praktischen, Direktzugriff mittels operator[] zusammen (?).

    MfG Ernesto



  • Ernesto schrieb:

    Mir ist in dem Zusammenhang noch ein nettes Feature aufgefallen: Wenn die Position auf die ich zugreifen will größer ist als die Länge der Liste, wird die Liste einfach nochmal durchgezählt.

    Nach dem C++ Standard ist das Verhalten davon nicht definiert. Ich rate dir von diesem trial-and-error ab. Davon kannst du nicht ableiten, was nach dem Standard erlaubt ist und was nicht.



  • Danke für die Warnung.
    Wenn dieses 'feature' nicht im C++ Standard definiert ist, kann es also sein, dass dieses je nach Compiler enthalten ist oder auch nicht (?).

    So oder so ist das ursprüngliche Thema erledigt 😉

    MfG Ernesto


Log in to reply