map iterator vs. const_iterator



  • Hallo zusammen,

    diesmal wende ich mich mit einer Frage an euch, bei der ich nicht
    sicher bin ob ich alles richtig verstanden habe.

    Folgende Situation:
    Ich habe eine Map mit Identifier std::string und Elementen der Klasse c_mytype.
    Die Klasse c_mytype hat z.B. die Funktion get_myname()

    Nun möchte ich mit einem Iterator über die Map laufen und alle get_myname Funktionen der Eintraege aufrufen.

    Zuerst habe ich es so gemacht:

    map<string, c_mytype>::const_iterator beg=mymap.begin();
    map<string, c_mytype>::const_iterator end=mymap.end();
    while (beg!=end) {
       string dername;
       dername = mymap[beg->first].get_myname();
       beg++;
    }
    

    Allerdings störte mich daran, dass ich ja dann jedes Mal einen zusätzlichen Map-Zugriff habe, was wie ich denke bei vielen Einträgen nicht performanceoptimal sein dürfte.

    Also wollte ich statt

    dername = mymap[beg->first].get_myname();
    

    dann

    dername = beg->second.get_myname();
    

    benutzen.

    Allerdings mag das der Compiler nicht (folgende Meldung):
    test2.cpp:90: Fehler: Die Übergabe von »const c_mytype« als »this«-Argument von »std::string c_mytype::get_myname()« streicht Qualifizierer

    Ok, der "Fehler" war schnell ausgemacht, denn const_iterator liefert ja ein const Element zurück, das ich nicht verändern darf.
    Also einfach das const_iterator durch iterator ausgetauscht und alles funzt.

    Nun aber meine Fragen:
    Gibt es bei dieser Vorgehensweise ein Problem?
    Ist die Verwendung von Iterator statt const_iterator und damit der direkte Zugriff ueber beg->second wirklich schneller?
    Ist der Unterschied der beiden Iteratoren wirklich nur, dass das Iteratorelement bei const geschützt ist?

    Vielen Dank schonmal.
    Marius



  • Du musst get_myname als const Funktion deklarieren. Zumindest der Name deutet an, dass sie auch const ist.

    Der direkte Zugriff über den Iterator (also it->second) ist schneller. Deine erste Variante mit den [] direkt wieder vergessen. Die Frage, ob map::iterator oder map::const_iterator hat damit nichts zu tun; beide sind gleich schnell.

    Der const_iterator schützt den Inhalt der Map vor Veränderungen, d.h. Du darfst nur Sachen mit den Map Elementen treiben, die den Inhalt nicht ändern. Du kannst die Werte z.B. kopieren oder Funktionen, die als "const" markiert sind aufrufen. Den Schlüssel darfst (solltest) Du sowieso nicht ändern, der ist per se const.



  • Gut den Schlüssel wollte ich eh nicht ändern.
    Aber die get_myname() Funktion war nur ein Beispiel.
    Es gibt auch Funktionen in der Klasse, die etwas an dem Element selbst ändern.
    Somit werde ich wohl den iterator statt const_iterator nehmen.

    Wollte auch nur sichergehen, dass ich dabei nicht einen Nachteil dieser Methode übersehe.

    Danke 🙂



  • der direkte zugriff ist definitiv schneller. warum verwendest du überhaupt einen const_iterator 😕 das ist doch garnicht nötig.



  • Konfusius schrieb:

    der direkte zugriff ist definitiv schneller. warum verwendest du überhaupt einen const_iterator 😕 das ist doch garnicht nötig.

    Weil ich das ursprünglich in Beispielen gelesen habe.
    Und irgendwie wird in den meisten Beispielen die ich bei google zu Iteration gefunden habe der const verwendet...



  • Einen Geschwindigkeitsunterschied zwischen map::iterator und map::const_iterator gibt es nicht. Das ist also kein Grund sich für die eine oder andere Variante zu entscheiden.

    2 Gründe warum man map::const_iterator nehmen kann/muss:
    1. die map ist als const deklariert, z.B.

    void find( const map<string, int>& theMap);
    

    Dann geht nur der const_iterator innerhalb der Routine find.

    2. Aus Dokumentationsgründen:
    const_iterator sagt dem Leser des Codes, dass hier die Objekte der Map nicht geändert werden. In einem kurzen Codeteil weniger wichtig, bei längeren Routinen (die man allerdings eh vermeiden sollte) oder bei Übergaben an andere Routinen finde ich das sehr hilfreich.


Anmelden zum Antworten