[ERLEDIGT] iterator und const iterator



  • Hallo Leute,
    ich habe eine Suchfunktion die mir sagen soll ob und wo sich eine Koordinate mit einer ID in einer MAP befindet.

    Diese Position soll eine zweite Funktion nutzen um eben diese Koordinate zu löschen.

    Irgendwie bekomme ich den CAST nicht hin.

    typedef std::map<unsigned int,UTM, std::greater<unsigned int>>::iterator UTM_ITERATOR;
    typedef std::map<unsigned int,UTM, std::greater<unsigned int>>::const_iterator UTM_CONST_ITERATOR;
    
    UTM_CONST_ITERATOR GEOTopology::find_coordinate_by_id(unsigned int &searched_id) const{
    	UTM_CONST_ITERATOR utmiterator = coordinates.find(searched_id);
    	//If the coordinate id is not found, iterators (it) position is list end.
    	if(coordinates.end() != utmiterator) return utmiterator;
    	else return NULL;
    }
    
    void GEOTopology::remove_coordinate(unsigned int useless_id){
    
    	//Does the coordinate id exists in the coordinate map?
    	UTM_ITERATOR tmppos = (UTM_ITERATOR) find_coordinate_by_id(useless_id);
    	if(NULL != tmppos) coordinates.erase(tmppos);
    	else exit(1);
    }
    

    In Zeile 14 geht es schief. Ich weiß dass es am Funktionsflag const liegt.
    Ist es in diesem Fall sinnvoll den Const flag zu behalten?
    Vielleicht kann man es ja intelligenter lösen.



  • Erstelle eine weitere find_coordinate_by_id -Methode ohne const .



  • TyRoXx schrieb:

    Erstelle eine weitere find_coordinate_by_id -Methode ohne const .

    OK, hat sich erledigt.
    Jetzt sieht es so aus:

    typedef std::map<unsigned int,UTM, std::greater<unsigned int>>::iterator UTM_ITERATOR;
    
    UTM_ITERATOR GEOTopology::find_coordinate_by_id(unsigned int &searched_id){
    	UTM_ITERATOR utmiterator = coordinates.find(searched_id);
    	//If the coordinate id is not found, iterators (it) position is list end.
    	return coordinates.end() != utmiterator ? utmiterator : NULL;
    }
    
    void GEOTopology::remove_coordinate(unsigned int useless_id){
    
    	//Does the coordinate id exists in the coordinate map?
    	UTM_ITERATOR tmppos = find_coordinate_by_id(useless_id);
    	(coordinates.end() != tmppos) ? coordinates.erase(tmppos) : exit(1);
    }
    

    Vielleicht weiß ja einer wie es mit const zu lösen wäre. Read Only Funktionen sollten ja mit const versehen sein.



  • Mir erscheint dein gesamtes Konzept etwas merkwürdig... Warum gibst du NULL zurück? Was soll der Sinn dieser Funktion sein? Ob das Element existiert oder nicht, ist mit end bereits aussagekräftig bekannt.



  • void GEOTopology::remove_coordinate(unsigned int useless_id)
    {
        UTM_ITERATOR tmppos = coordinates.find(useless_id);
    
        if (coordinates.end() != tmppos) 
           coordinates.erase(tmppos);
        else 
           exit(1);
    }
    

    Done.



  • ... schrieb:

    Mir erscheint dein gesamtes Konzept etwas merkwürdig... Warum gibst du NULL zurück? Was soll der Sinn dieser Funktion sein? Ob das Element existiert oder nicht, ist mit end bereits aussagekräftig bekannt.

    Danke für den Tipp. Du hast natürlich recht.

    ... schrieb:

    void GEOTopology::remove_coordinate(unsigned int useless_id)
    {
        UTM_ITERATOR tmppos = coordinates.find(useless_id);
    
        if (coordinates.end() != tmppos) 
           coordinates.erase(tmppos);
        else 
           exit(1);
    }
    

    Done.

    Die Suchfunktion wird an vielen Stellen gebraucht, deswegen wollte ich sie mal auslagern..



  • Warum...
    ...akzeptierst Du in Zeile 4 search_id als Referenz?
    ...glaubst Du, man könne Iteratoren mit NULL initialisieren oder vergleichen?
    ...glaubst Du, man könne einen const_iterator in einen iterator konvertieren?

    kk



  • krümelkacker schrieb:

    Warum......akzeptierst Du in Zeile 4 search_id als Referenz?

    Weil ich sie nirgendwo manipuliere. Ist das nicht ok?

    krümelkacker schrieb:

    ...glaubst Du, man könne Iteratoren mit NULL initialisieren oder vergleichen?

    Anscheinend nicht. Dank diesem Forum weiß ich es jetzt.

    krümelkacker schrieb:

    ...glaubst Du, man könne einen const_iterator in einen iterator konvertieren?

    Bisher dachte ich es. Anscheinend nicht. Den Grund wüsste ich gerne, vielleicht hat jemand dafür eine gute Begründung. Link?



  • void a(int& x)
    {
     x = 100;
    }
    
    void b(int x)
    {
     x = 200;
    }
    
    int main()
    {
     int bsp = 50;
     std::cout << bsp << "\n"; // 50
     a(bsp);
     std::cout << bsp << "\n"; // 100 (Referenz bei a, Wert überschreiben)
     b(bsp);
     std::cout << bsp << "\n"; // 100 (Keine Referenz bei b, Wert bleibt erhalten)
    }
    

    Näheres dazu bitte selber mit Google raussuchen.



  • Man kann das const durchaus wegcasten. Ob das standardkonform ist, weiß ich nicht. Fakt ist, dass krümelkacker unrecht hat.

    #include <iostream>
    #include <string>
    #include <map>
    
    typedef std::map<std::string, std::string> TestMap;
    
    int main()
    {
    	TestMap test;
    
    	test["Test"] = "Ein Test!";
    
    	TestMap::const_iterator constIt = test.find("Test");
    
    	std::cout << constIt->second << std::endl;
    
    	// Und nun machen wir aus dem const_iterator einen iterator
    	TestMap::iterator *nonConstIt = reinterpret_cast<TestMap::iterator *>(&constIt);
    
    	(*nonConstIt)->second = "Haha!";
    
    	std::cout << test["Test"] << std::endl;
    
    	return 0;
    }
    

    Bitte nicht nachmachen. Das ist mehr als hässlich. Dient nur zur Abschreckung 🤡



  • ... schrieb:

    ....

    In meinem Fall verändere ich ja die Variable nicht, also kann die Referenz stehen bleiben. Oder nicht?



  • darkfate schrieb:

    ... schrieb:

    ....

    In meinem Fall verändere ich ja die Variable nicht, also kann die Referenz stehen bleiben. Oder nicht?

    In dem Fall brauchst du die Referenz aber gar nicht.

    http://tutorial.schornboeck.net/referenzen.htm



  • ... schrieb:

    ....

    Dann wird aber beim Betreten der Funktion doch unnötig kopiert?



  • darkfate schrieb:

    krümelkacker schrieb:

    Warum......akzeptierst Du in Zeile 4 search_id als Referenz?

    Weil ich sie nirgendwo manipuliere. Ist das nicht ok?

    Was ist das denn für eine Logik?

    darkfate schrieb:

    krümelkacker schrieb:

    ...glaubst Du, man könne einen const_iterator in einen iterator konvertieren?

    Bisher dachte ich es. Anscheinend nicht. Den Grund wüsste ich gerne, vielleicht hat jemand dafür eine gute Begründung. Link?

    Wenn das ginge, würde die Unterscheidung zwischen iterator und const_iterator keinen Sinn machen. Dann kann ja jeder daher kommen und einen const_iterator in einen iterator verwandeln und böse Dinge anstellen. Eine interessantere Frage wäre: Warum akzeptiert die erase-Methode keinen const_iterator? Antwort: An so etwas hat man wahrscheinlich nicht gedacht beim Design.

    kk



  • darkfate schrieb:

    ... schrieb:

    ....

    Dann wird aber beim Betreten der Funktion doch unnötig kopiert?

    Jein. Im Fall einer extrem großen Klasse, etc. wäre das sicher ein Punkt, wo man drauf achten kann. Oft wirst du daher auch im Forum const std::string& str als Parameter sehen. Bei einem int ist das aber vollkommen überflüssig. Der Datentyp ist so klein. Ich bin mir nicht sicher, aber eventuell macht die Referenz es in dem Fall sogar noch langsamer 😃 Also merke dir: Bei den "eingebauten" Datentypen macht das keinen Sinn und ist überflüssig.



  • Das ist ein int , der kostet so gut wie gar nichts beim Kopieren. Außerdem verbraucht die Referenz auch Speicher und CPU-Zeit, vielleicht sogar noch mehr.



  • krümelkacker schrieb:

    darkfate schrieb:

    krümelkacker schrieb:

    Warum......akzeptierst Du in Zeile 4 search_id als Referenz?

    Weil ich sie nirgendwo manipuliere. Ist das nicht ok?

    Was ist das denn für eine Logik?

    darkfate schrieb:

    krümelkacker schrieb:

    ...glaubst Du, man könne einen const_iterator in einen iterator konvertieren?

    Bisher dachte ich es. Anscheinend nicht. Den Grund wüsste ich gerne, vielleicht hat jemand dafür eine gute Begründung. Link?

    Wenn das ginge, würde die Unterscheidung zwischen iterator und const_iterator keinen Sinn machen. Dann kann ja jeder daher kommen und einen const_iterator in einen iterator verwandeln und böse Dinge anstellen. Eine interessantere Frage wäre: Warum akzeptiert die erase-Methode keinen const_iterator? Antwort: An so etwas hat man wahrscheinlich nicht gedacht beim Design.

    kk

    Wird beim Aufruf von erase nicht der Iterator ungültig? Eventuell wird dieser überschrieben und auf end gesetzt. Ich traue den Entwicklern durchaus einiges zu und schließe daher ein Designfehler aus. 🤡



  • darkfate schrieb:

    ... schrieb:

    ....

    Dann wird aber beim Betreten der Funktion doch unnötig kopiert?

    Wir sprechen hier von einem int! Und überhaupt, wenn man bei einem nicht-trivialen benutzerdefinierten Typen das Kopieren sparen will, benutzt man Referenzen auf const:

    double vector_sum(vector<double> const& rac); // ref-auf-const
    


  • Ok die Referenz wird entfernt. Demokratisch..



  • Was passiert eigentlich mit der find() funktion wenn ich mehrere Werte habe? Bleibt sie beim ersten Wert stehen?



  • darkfate schrieb:

    Was passiert eigentlich mit der find() funktion wenn ich mehrere Werte habe? Bleibt sie beim ersten Wert stehen?

    Einem Key ist nur 1 Wert zugeordnet.


Anmelden zum Antworten