const_iterator



  • Was diesen debuggenden Iterator angeht macht der sowieso nicht was Du möchtest, da er einen Anfang-Iterator und offenbar einen Zeiger des enthaltenen Containers erwartet. Diesen "fragt" er vermutlich wo das Ende ist - was bei einem NULL-Zeiger logischerweise auch nicht funktioniert.

    Desweiteren finde ich nirgendwo, in keiner Beschreibung der C++ Standardbibliothek eine Anwendung des string::const_iterator wie Du ihn benutzt.

    Fazit:
    Hättest Du es von Anfang nach Standard gemacht hättest Du jetzt vermutlich kein Problem (sorry, aber ist die Wahrheit)



  • LordJaxom schrieb:

    Hättest Du es von Anfang nach Standard gemacht hättest Du jetzt vermutlich kein Problem (sorry, aber ist die Wahrheit)

    Witzbold!

    bool foo(string::const_iterator iBegin, string::const_iterator iEnd)
    {
    ...
    return true;
    ...
    return false;
    }
    

    das ist doch wohl Standardkonform oder?
    Nun bekomme ich leider ein const char Array und soll dann weiter machen. Hat bisher auch alles wunderbar geklappt. Ich habe mir das nicht einfallen string::const_iterator(ptr,this). Das einzige was mir bis jetzt eingefallen ist den Securitykram wieder weg zu machen.



  • idefix schrieb:

    Witzbold!

    Nö, war eigentlich garnicht humoristisch gemeint, habe deshalb sogar absichtlich auf Smileys verzichtet.

    bool foo(string::const_iterator iBegin, string::const_iterator iEnd)
    

    das ist doch wohl Standardkonform oder?

    Ja, das ist Standardkonform.
    Das jedoch nicht:

    iBegin =std::string::const_iterator(sz,NULL);
    

    Aber wenn Du eine allgemeingültige Funktion möchtest die mit String-Iteratoren als auch Array-Iteratoren klarkommt, mach es doch wie die Standardbibliothek selbst:

    template<typename FwdIt>
    bool foo(FwdIt iBegin, FwdIt  iEnd)
    

    Lässt sich aufrufen mit:

    const char* hello = "Hello";
    foo(hello, hello + strlen(hello));
    
    std::string world = "World";
    foo(world.begin(), world.end());
    


  • benutzt du eigentlich VC8 LordJaxom?



  • Was hat das mit Standardkonformen Code zu tun?

    Aber ja, ich habe Zugang zu einem VC8 und probiere damit auch meistens aus, was ich hier lese, private entwickle ich jedoch fast nur mit G++.



  • Gut. So gar sehr gut.

    Das const_iterator(sz,NULL) nicht Standardkonform ist mir schon klar.
    Wenn ich aber den Standard wie folgt benutze:

    iBegin=std::string::const_iterator(sz);
    

    dann bekomme ich folgende Fehlermeldung

    error C2440: '<function-style-cast>' : cannot convert from 'char [6]' to 'std::_String_const_iterator<_Elem,_Traits,_Alloc>'
    1>        with
    1>        [
    1>            _Elem=char,
    1>            _Traits=std::char_traits<char>,
    1>            _Alloc=std::allocator<char>
    1>        ]
    1>        No constructor could take the source type, or constructor overload resolution was ambiguous
    

    Und nun?

    Das Gleiche passiert auch mit iterator. Mir ist einfach nicht klar warum MS das so geändert hat und warum es jetzt Defines gibt, die das wieder aufheben. Das wird doch zu ein großen Drucheinander führen. Was auch nicht mehr geht ist:

    const char *pszstr = str.begin();
    


  • Warum Microsoft es ändert, kann ich Dir natürlich nicht sagen, was ich aber sagen kann, ist dass Microsoft das Recht hatte das zu tun. Der Standard schreibt nämlich nicht vor, dass ein String-Iterator ein Character-Pointer sein muss. Er kann es sein, muss es aber nicht. Es ist nur vorgeschrieben dass er sich (im Falle Random-Access-Iterator) wie ein Zeiger verhält.

    Thinking in C++, Kapitel 1: Strings schrieb:

    Iterators are themselves objects which move through a collection or container of other objects, selecting them one at a time, but never providing direct access to the implementation of the container. Iterators are not pointers, but they are useful for many of the same jobs.

    In manchen Implementierungen wird Dein Code also funktionieren, in anderen nicht. Hier hat Microsoft wohl einen Grund gesehen die (ehemals als const char*) Implementierung von const_iterator zu ändern.

    Der Grund warum die meisten Iteratoren nicht ineinander konvertierbar sind ist denke ich einfach dass o.a. Template-Lösungen die auf irgendeinem Forward-Iterator arbeiten flexibel genug sind dass eine Konvertierbarkeit nicht erforderlich ist.

    BTW:
    Mit einem G++ 3.2 funktioniert das erste Snippet sogar noch, das zweite jedoch schon nicht mehr.



  • Warum Microsoft das geändert hat ist klar.

    Die Sache ist so: der Standard spezifiziert, was ein std::string::const_iterator zu können hat. Was er darüber hinaus kann, ist undefiniert.

    Eine einfache (und schnelle) Implementierung ist es, std::string::const_iteartor als const char* über ein typedef gleich zu setzen. Der Implementierer kann aber auch eine Klasse implementieren, die weitere Features, wie z. B. zusätzliche Prüfungen realsiert. Solange der Iterator alles kann, was er können soll, ist das legitim und sogar im Sinne des Erfinders.

    Eine const_iterator-Klasse, die Prüfungen macht, ist natürlich sicherer, aber langsamer als ein const char*, hat also seine Vor- und Nachteile. Daher ist das durchaus Sinnvoll, das über den Präprozessor ein- und ausschaltbar zu machen, so daß das Programm im debug-code mit Netz und doppelten Boden arbeitet und im release-code dann mit voller Geschwindigkeit.



  • Also letztendlich bedeutet das:

    Übergang von C/C++ nach stl
    oder vielleicht besser von nicht stl nach stl

    char szSource[]="Hello";
    char szResult[255];
    
    //jetzt Übergang
    string s;
    s=string(szSource);
    //weiter mit stl
    .....
    //wieder zurück
    strcpy(szResult,s.c_str());
    

    Das ist aber äußerst unbefriedigend. Warum muß ich den kopieren? Wenn ich den Quelle garnicht bearbeiten will.



  • Vielleicht wäre es einfacher, die empfangende Funktion in eine Template-Funktion umzubauen die wie die Standard-Algorithmen mit beliebigen Iteratoren (also auch char* bis char*+laenge) klarkommt. Den Ansatz dafür habe ich ja schon gepostet 😉



  • Moin,

    ich muß ja zugeben das ich die Zuweisung eines const char* an einen string::const_iterator missbräuchlich verwendet habe. Aber es funktionierte eben sehr gut. Nach langem hin und her, habe ich mir einen eigenen Iterator geschreiben, der mit dieser Zuweisung sehr gut um gehen kann. Ich habe mich immer etwas gescheut einen eigenen Iterator zuschreiben, aber so schwer ist das auch wieder nicht. Hier kam mir der Vorteil von Templates sehr entgegen, denn ich brauchte nicht alles um schreiben.

    Eine Frage bleibt trotzdem. Ist ein C-String überhaupt in std::string konvertierbar ohne da dieser kopiert werden muß? Oder interpretiert die STL C-Strings und Strings gänzlich voneinander getrennt?


Anmelden zum Antworten