Iterator Frage die Zweite



  • lettort schrieb:

    Natürlich zwingt mich keiner irgendwas zu benutzen, aber es sollte doch fragwürdig sein zwei Structs (begin + end), anstatt zwei int's zu nutzen(0 und size()), oder?

    Aha? Also glaubst du doch, das es was mit Performance zu tun hat? Sonst würdest du struct und int nicht gegeneinander ausspielen wollen? Klar, struct und int sind zwei verschiedene Datentypen. Aber performancemäßig wirkt sich das in dem Fall nicht aus. Hat was mit Nicht-Polymorpth und Operator-Überladung zutun. Ich bezweifel mal, das auch der Compiler das end() nicht weg optimieren kann, da es sicherlich inline und const ist.

    Für mich pers. würde die Frage Iterator Ja/Nein nur wegen der Schreibarbeit auftauchen.



  • Dann brauche ich ja trotzdem 2 Iteratoren - begin und end.

    jupp .... aber keiner weiss was die Impl hinter dem container treibt. Es ist anzunehmen, das er den speicher fuer das begin() und das end() bzw deren iteratoren, gleich mit anlegt, und beim befuellen oder beim abrufen aktualisiert.

    so braucht man beim aufruf der end() funktion eigentlich nur nen vorhanden iterator kopieren, da iteratoren recht klein sind (zeiger + ggf. paar verwaltungsinformationen), nen relativ geringer aufwand.

    Wo ist dann bitte der Sinn dahinter ?

    einheitliches Konzept / schnittstelle auf unterschiedliche container ?
    Iterier mal mitm index auf ner verketteten liste ^^

    Kann dann auch gleich in einer Schleife direkt aus dem Vector mir die Werte geben lassen und ständig überprüfen ob Vector::size() erreicht ist.

    wobei du dir sicher sein kannst, dass bei nem vector auf zeigerdressen optimiert wird ^^ nen iterator verhaelt sich uebrigens fast wien zeiger auf nen array ^^

    ne typische iteratorschleife sieht meist so aus :

    for(std::vector<int>::iterator it = myvec.begin(); it != myvec.end();++it)
    {
    }
    

    das ganze mal auf nen statisches array gemuenzt:

    int mytestvector[255]; 
    for(int * iterator it = &mytestvector[0]; it != &mytestvector[255]; ++it)
    {
    }
    

    Kannst dir jetzt ca vorstellen was ne stl impl im hintergrund aus nem vector und dem iterator macht ??? Wenn dann der compiler noch bisserl optimiert, glaub kann man allein am assemblercode der iteratorschleife nimmer unterschieden obs nen std::vector oder nen reines array war ...

    Ciao ...



  • Mir persönlich ist die Frage Iterator Ja/Nein eine Frage des Engineering's und der Objektorientierung... vieleicht auch einfach nur ein persönliches Empfinden, aber es ist halt unschön Elemente einer Klasse dadurch zu bekommen, dass man sie von aussen iterieren muss.

    Mir wäre es halt lieb, so wie ich es z.B. aus Java gewöhnt bin, einen Iterator als Rückgabewert einer Methode zu bekommen, mit welchem ich dann die Elemente eines Containers durchforsten kann.

    z.B.:

    Iterator it = myObject.giveMeYourContent(); //gibt nen Iterator wieder.
    
    while ( (object = it.next()) != null) {
       // do something with object
    }
    

    Das schaut doch fein und säuberlich aus und dies war auch meine ganze Intention.



  • Ein Interator ist ja letztendlich nur ein schlauer Pointer. Ich kann den mit ++ und -- hoch und runter drehen um auf einem Container zu wandern.

    +------------------------------+
    +-------------+      | +----------+   +-----------+ |
    | Algorithmus |----->| | Iterator |-->| Container | |
    +-------------+      | +----------+   +-----------+ |
                         +------------------------------+
    

    Der Algo kann dabei eine einfache for-Schleife sein, oder auch ein std::sort(). Wenn ich nen int und size benutze, greife ich direkt auf den Container zu. Wenn ich nen Iterator habe, hab ich den Container getrennt. Und das ohne Performancenachteile.



  • while(++it_beg != t.end())
    {
      // Mach was mit *it_beg
    }
    


  • war zu langsam 😕

    lettort schrieb:

    Natürlich zwingt mich keiner irgendwas zu benutzen, aber es
    sollte doch fragwürdig sein zwei Structs (begin + end), anstatt zwei int's zu nutzen(0 und size()), oder?

    Denkanstoss:

    template<typename ContainerT>
    void print_all_dumb_solution(ContainterT const& c) {
      for(int i=0; i<c.size(); ++i) {
        cout<<c[i]<<' ';
      }
    }
    
    template<typename ForwardIter>
    void print_all_smart_solution(ForwardIter start, ForwardIter end) {
      while(start!=end) {
        cout<<*start<<' ';
        ++start;
      }
    }
    
    int main() {
      vector<int> v;
      v.push_back(3);
      v.push_back(7);
    
      print_all_smart_solution(v.begin(), v.end());
      print_all_dumb_solution(v);
    }
    

    klappt super oder?

    aber warte, ich will nur die 1. haelfte des containers ausgeben:

    print_all_smart_solution(v.begin(), v.begin()+v.size()/2+1);
      print_all_dumb_solution(???); //you are fucked :/
    

    ok, dumme sache das. ich brauch das ganze fuer ne liste:

    int main() {
      list<int> l;
      l.push_back(3);
      l.push_back(7);
    
      print_all_smart_solution(l.begin(), l.end());
      print_all_dumb_solution(l); //you are fucked :/
    }
    

    ok, nun will ich die zahlen verkehrt rum ausgeben:

    int main() {
      vector<int> v;
      v.push_back(3);
      v.push_back(7);
    
      print_all_smart_solution(v.rbegin(), v.rend());
      print_all_dumb_solution(v); //you are fucked :/
    }
    


  • lettort schrieb:

    Mir persönlich ist die Frage Iterator Ja/Nein eine Frage des Engineering's und der Objektorientierung... vieleicht auch einfach nur ein persönliches Empfinden, aber es ist halt unschön Elemente einer Klasse dadurch zu bekommen, dass man sie von aussen iterieren muss.

    Mir wäre es halt lieb, so wie ich es z.B. aus Java gewöhnt bin, einen Iterator als Rückgabewert einer Methode zu bekommen, mit welchem ich dann die Elemente eines Containers durchforsten kann.

    z.B.:

    Iterator it = myObject.giveMeYourContent(); //gibt nen Iterator wieder.
    
    while ( (object = it.next()) != null) {
       // do something with object
    }
    

    Das schaut doch fein und säuberlich aus und dies war auch meine ganze Intention.

    fein und säuberlich? Und was ist an den Iteratoren von C++ schlechter? Das bist du uns noch schuldig. Du machst im Prinzip das gleiche. Du holst dir in der esten Zeile den begin-Iterator (it) und erhöhst ihn mit next (bei C++ mit ++-Operator). Und ob das Ende angekommen ist, überprüfst du mit != null (auch ein Pointerwert!!!), in C++ überprüfst du gegen end (auch ein Pointerwert!).

    Du hast nicht weniger und nicht mehr gemacht. Nur in C++ hat man andere Sprachfeatures, wie z.B. Operatorüberladung. Warum soll ich den Iterator mit next erhöhen, wenn ich das auch mit ++ machen kann? Das ist doch nicht unsauberer?



  • lettort schrieb:

    ...

    Iterator it = myObject.giveMeYourContent(); //gibt nen Iterator wieder.
    
    while ( (object = it.next()) != null) {
       // do something with object
    }
    

    Das schaut doch fein und säuberlich aus und dies war auch meine ganze Intention.

    😕 Wo ist denn da der Unterschied zum C++-Code ? 😕

    Stört Dich, dass man "++" schreibt statt "next()" ?
    Und ist der Rückschluß "Hmmm, next() gibt mir null zurück; bin wohl am Ende der Liste" wirklich offensichtlicher als ein "== end()" ?

    Du scheinst wirklich nur etwas "javaverblendet" zu sein... 😉

    Gruß,

    Simon2.



  • Besser oder nicht Besser ist doch gar nicht die Frage. Ich habe einen Iterator wiederbekommen und mit dem einen kann ich arbeiten, bei c/C++ müsste ich mit zwei Iteratoren arbeiten, obwohl es nicht sein müsste.

    Ok, das Beispiel war nun unglücklich gewählt, hätte etwas machen sollen wo ich z.B. auf "iterator.hasNext()" (http://java.sun.com/j2se/1.4.2/docs/api/java/util/Iterator.html) reagiere, in einer while-schleife.

    Weiterhin kann man ja nette Spielchen mit den ITeratoren machen, wie der "Schatten" ja gezeigt hat. Aber man kann nicht mit einem Iterator durch sich selbst navigieren, ohne das man irgendwann das Problem hat, dass man auf einen segFAult zuläuft. Find ich halt Schade und auch nicht sinnig - aus objektorientierter Sicht gesehen.



  • Mir persönlich ist die Frage Iterator Ja/Nein eine Frage des Engineering's und der Objektorientierung

    Das iteratorkonzept ist a: Objektorientiert, und b: sogar nen reinrassiges Entwurfsmuster(Verhaltensmuster) oder ?

    Wenn mich jetzt noch nen Programmierer fragt, ob er Entwurfsmuster einsetzen soll oder ned ... ^^

    Ok, dein eigentliches problem scheint nen ganz anderes zu sein:

    "iterator.hasNext()"

    Glaub die STL designer ham sich schon gedanken gemacht, warum sie sowas ned unterstuetzen ...
    hasnext() ruft man nur auf, um zu ermitteln ob nen iterator (oder der folgende iterator) noch gueltig ist. die STL verzichtet expliziet auf sowas. weil:
    - dann gaengen keine reinen pointer aufn array mehr (alle stl allgos gehen auch mit c-array + pointer)
    - bei einigen containern (vector) waer es zusaetzlicher aufwand, das ding zu halten, und damit mehr zu kopieren.
    - die eigentliche iteratorschnittstelle wuerde groesser werden ...
    - das begin musst dir eh vom container holen, warum dann ned auch das end ?
    - bei teiliterationen,also dein end ist nicht deine abbruchbedingung, muesste das der iterator wissen, ergo bei unterschiedlichen iterationen unterschiedliche itaerator typen ? oder gar ne kopie des container-Anteil erzwingen den man iterieren will ?

    Ciao ...



  • lettort schrieb:

    Besser oder nicht Besser ist doch gar nicht die Frage....

    Naja:

    lettort schrieb:

    ...Wo ist dann bitte der Sinn dahinter?...Schade und auch nicht sinnig ...obwohl es nicht sein müsste...

    Das klingt schon kaum noch "wertfrei".

    lettort schrieb:

    ...hätte etwas machen sollen wo ich z.B. auf "iterator.hasNext()" (http://java.sun.com/j2se/1.4.2/docs/api/java/util/Iterator.html) reagiere, in einer while-schleife....Schade und auch nicht sinnig - aus objektorientierter Sicht gesehen.

    😮 also spätestens DA hast Du doch Deinen "2. iterator" ... wo ist denn der Unterschied zwischen "!=end()" und "hasNext()" ?
    Kann es sein, dass Du "iterator" als vollwertiges Objekt nicht wahrgenommen hast, sondern nur als "emantisches Konstrukt zur Durchführung einer Schleife" ?
    Was soll an zweiter const-iteratoren, die Anfang und Ende einer Liste kennzeichnen verwerflich sein ?

    Ach ja: Eventuell wirds auch beim Thema "const" ein wenig schwammig, wenn man von Java herkommt.

    Gruß,

    Simon2.

    P.S.: Noch eine Frage: Gibt's bei Java eigentlich auch previous()/hasPrevious() ?



  • Dein Problem ist, das du sagst "DAs was Java macht, ist sauberer.". Gut, das ist deine Meinung. Aber letztendlich ist !=null fachlich gesehen, nicht logisch. Weil ich damit nur überprüfe, ob ein Itertor auf null zeigt. Aber hat das was mit DEM Ende zu tun?

    Letztendlich beisst du dich auf end() fest, obwohl es überhaupt keinen Grund gibt. Was stört dich an end()? Es ist sogar eine aussagefähige Methode, es sagt "Da ist DAS Ende." Schöner kann eine Hochsprache etwas nicht aussagen. null heißt eigentlich nur in Pointer-Jargon "ungültig". Macht im Container eigentlich wenig Sinn.

    Stört dich die Performance? Es gibt dadurch keinen Nachteil.

    Stört dich die Schreibarbeit? Gut, kann sein, ich tippe ein paar Buchstaben mehr ein. Super! In dem Fall ist das Iterator-Konzept gescheitert. 😃

    Also, man kann sich auch "anstellen" und haarspalterei betreiben.



  • Nur um es mal klarzustellen - ich bin an diese Diskusion völlig wertefrei herangegangen, da ich in beiden Programmiersprachen Vor- und Nachteile sehe und beides gern einsetze.

    Was momentan wohl etwas untergegangen ist, ist die Tatsache das ich bei C++ einen Iterator .begin und einen Iterator .end vom Vector hole. Bei Java hat der Iterator selbst eine Ahnung über sein .end und .begin.



  • lettort schrieb:

    Find ich halt Schade und auch nicht sinnig - aus objektorientierter Sicht gesehen.

    Begruendung?

    "Weils bequemer ist" zaehlt nicht.
    Es hat nichts mit objekt orientierung zu tun ob du immer ein iteratoren paar brauchst oder nicht.

    was zaehlt ist die abstraktion - und da tut es nichts zur sache ob du 1 oder 100 iteratoren brauchst...

    unbequem ist es manchmal, ja. aber bequemlichkeit ist kein konzept der OOP...



  • @lettort

    kenn mich in java ned so aus. Aber gilt dein iterator auch fuer maps (assoziative container, key - wert Speicher) ?

    wenn ja, dann schreib mal wie man in java ueber so ne map iterieren wuerd, wenn man zb alle keys von 10 - 100 haben wollt (integer - irgendwas map) !
    Bin echt neugierig wie java da einen untrstuetzt ...

    Ciao ...



  • lettort schrieb:

    ...Was momentan wohl etwas untergegangen ist, ist die Tatsache das ich bei C++ einen Iterator .begin und einen Iterator .end vom Vector hole. Bei Java hat der Iterator selbst eine Ahnung über sein .end und .begin.

    DAS stimmt natürlich !
    Ist halt die Frage, ob Anfang und Ende eher Eigenschaften eines Iterators oder eines Containers ist ... ich persönlich empfinde es eher als Container-Eigenschaften ("Am Ende einer Liste ... der Anfang einer Tabelle ..."); aber das ist erstmal emotional begründet.

    Gruß,

    Simon2.



  • Man kann jetzt wieder viel philosophieren...

    Ein Iterator ist doch ein Objekt, welches einen Containerinhalt schrittweise wiedergeben kann. Wenn dieses Objekt also einen Inhalt besitzt, dann wäre es doch sinnig, dass es über sein eigenes Ende bescheid weiss.

    Es kann ja nicht im OO-Kontext sein, dass ein Aussenseiter sich noch Gedanken darüber machen muss, dass er ein Ende "überfährt".

    So Jungens und Mädels, ich danke für die anregende Diskusion, muss sie aber leider auf Morgen vertagen!
    Wünsch euch allen das Beste! 😉

    @RHBaum
    Ich hoffe ich vergesse es bis morgen net. Will dran denken und dir ne Lösung geben.



  • Naja, das empfinden entwickelt sich auch ^^

    Als ich mein erstes template gesehen hab, dacht ich nur noch : "Um Gottes willen, was ist das denn ?".
    Mittlerweile find ich templates elegant und schoen ^^

    Denk mal das Java programmierer da echt etwas anders gepraegt sind, und mit c++ erst mal bisserl warm werden muessen.

    ob das begin und end am iterator ist, iss fuer mich ned nur ne geschmackssache ... sondern auch ne frage der performance und der flexibilitaet der iteratoren.

    Ciao ...



  • lettort schrieb:

    ...
    Ein Iterator ist doch ein Objekt, welches einen Containerinhalt schrittweise wiedergeben kann. Wenn dieses Objekt also einen Inhalt besitzt, dann wäre es doch sinnig, dass es über sein eigenes Ende bescheid weiss....

    Für mich ist ein iterator eher ein inhaltsloses Objekt ... eber ein "mobiler Griff", den man über die Elemente eines Containers schieben und über den man auf das jeweilige Objekt geeignet (const oder nicht) zugreifen kann. (bei const_iterator habe ich immer das Bild einer "Lupe" vor Augen).
    Den Iterator zu fragen, ob in dem Container, auf den ich ihn geschoben habe, noch Elemente (davor ? danach ?) sind, emfpinde ich eben als nicht natürlich.
    BTW: Gibt's in Java auch bidirectionale oder Random-Access-Iteratoren ? Immerhin kann ich mich in C++ auch mittels "--it" oder "it += 3" über eine Liste bewegen ... da ist ein "hasNext()" wenig hilfreich.

    Schönen Abend noch,

    Simon2.



  • lettort schrieb:

    Ein Iterator ist doch ein Objekt, welches einen Containerinhalt schrittweise wiedergeben kann. Wenn dieses Objekt also einen Inhalt besitzt, dann wäre es doch sinnig, dass es über sein eigenes Ende bescheid weiss.

    ja, und?

    Es waere auch "sinnig" dass ein Vogel eine "flieg()" methode hat, oder?
    Aber die Erfahrung hat gezeigt, dass n Pinguin und ein Strauss Voegel sind die nicht fliegen koennen.

    Ist es jetzt un-oo wenn ich Behaviors einbaue?

    Es kann ja nicht im OO-Kontext sein, dass ein Aussenseiter sich noch Gedanken darüber machen muss, dass er ein Ende "überfährt".

    Warum?

    Das sind ploetzlich 2 verantwortungen in einem Objekt:

    1. ist es ein iterator im C++ sinne - also ein "zeiger" auf den inhalt der Collection
      und
    2. ist es ploetzlich eine iteratoren-range.

    Ist das nicht genauso eine Schwachstelle wie dass man in c++ immer ein iteratoren paar braucht?

    Was ist jetzt besser? Was ist mehr OO?

    Ist es nicht einfach so, dass es 2 Loesungen fuer 1 Problem sind?

    Dass Iterator in Java eher ein IteratorRange ist? Ein high level konzept. und das iteratoren konzept in C++ eher low leveliger?

    OT:
    wenn dir soviel daran liegt dass iteratoren eine range sein sollen, dann mach doch eine iterator_range klasse die ein iteratore paerchen nimmt und deine .next und so methoden anbietet.


Anmelden zum Antworten