Komisches Verhalten von std::string?



  • Bassmaster schrieb:

    krümelkacker schrieb:

    Das hast du nicht wissen zu müssen.

    Ok, aber interessant wäre es dennoch.

    Das ist ja gerade der Witz an so einer Klasse wie std::string, dass man nicht wissen muss, wie die implementiert ist, sondern nur ihre Schnittstelle zu kennen braucht, um std::string benutzen zu können.

    Ich bin mir sicher, dass du auch herausfinden kannst, wie std::string funktioniert, wenn du dir den entsprechenden Header (und seine Abhängigkeiten) anschaust. std::string ist nämlich im Sinne des C++ Sprachkerns ein Benutzer-definierter Typ, der dir typischerweise in Quellform zur Verfü+gung steht.

    Der andere Witz an std::string ist, dass der C++ Standard nur die Schnittstelle spezifiziert und den Compiler-Herstellern bzw Bibliotheksautoren gewisse Freiheiten lässt. Beispielsweise funktioniert std::string aus libstdc++ vom GCC ganz anders als Microsoft's std::string Implementierung. Ersterer verwendet Referenzzählung und hat std::string so implementiert, dass sizeof(char*)==sizeof(std::string) gilt. Microsoft hat auf Referenzzählung verzichtet und seine Klasse für kurze Strings optimiert (small string optimization), wobei kurze Strings direkt im Objekt gespeichert werden und längere indirekt, also im Freispeicher. Deswegen ist so ein Ding, also sizeof(std::string) bei Microsoft auch viel größer ... mindestens 16 Bytes oder sowas, die Zahl habe ich nicht genau im Kopf.

    Der Punkt ist nur, dass du nicht irgendwelche Implementierungsdetails voraussetzen solltest, weil du damit unportablen und zerbrechlichen Code erzeugen würdest. Zerbrechlich deswegen, weil in einer neuen Compiler-Version die std::string-Implementierung geändert werden könnte und dann läuft dein Programm nicht mehr.



  • Ethon schrieb:

    Stell dir vor der String wäre refcounted, dann wäre die Hölle los.
    Ein String kann auf sehr viele unterschiedliche Arten implementiert sein.

    Seit C++11 kann ein string nicht mehr refcounted sein.



  • refcounted schrieb:

    Seit C++11 kann ein string nicht mehr refcounted sein.

    Ich glaube, das ist Quatsch, den du nur nachplapperst.
    Kannst du das denn auch belegen?



  • Ethon schrieb:

    Beschreibe im asm-Code einen const char*

    Höö?



  • krümelkacker schrieb:

    refcounted schrieb:

    Seit C++11 kann ein string nicht mehr refcounted sein.

    Ich glaube, das ist Quatsch, den du nur nachplapperst.
    Kannst du das denn auch belegen?

    21.4.1/6 schrieb:

    References, pointers, and iterators referring to the elements of a basic_string sequence may be invalidated
    by the following uses of that basic_string object:
    — as an argument to any standard library function taking a reference to non-const basic_string as an
    argument.233
    — Calling non-const member functions, except operator[], at, front, back, begin, rbegin, end, and
    rend.

    Damit std::string geshared (refcounted) sein könnte, müsste operator[] die Iteratoren ungültig machen.


  • Mod

    krümelkacker schrieb:

    refcounted schrieb:

    Seit C++11 kann ein string nicht mehr refcounted sein.

    Ich glaube, das ist Quatsch, den du nur nachplapperst.
    Kannst du das denn auch belegen?

    Doch das ist schon richtig. In C++11 wurde geändert, was Iteratoren und Referenzen auf basic_string-Objekte ungültig macht. Der Sinn dahinter ist bessere Unterstützung für multithreaded-Zugriffe. Dadurch wird indirekt ref-counting ausgeschlossen. Die libstc++-Entwickler sind sich dieser Tatsache bewusst, aber ich weiß nicht, ob dies in der jüngsten Version schon überarbeitet ist. Jedenfalls war die Implementierung eine ganze Weile lang nicht C++11-standardkonform, da noch die alte Implementierung beibehalten wurde.

    edit: Viel zu langsam.



  • Danke für das Zitat ... also streng ausgeschlossen wird das jetzt nicht, aber eine ref-counted Implementierung müsste, bevor sie überhaupt Iteratoren oder Referenzen rausgibt, dafür sorgen, dass die Zeichenkette nicht mehr mit anderen string-Objekten geteilt wird. Ob sich das dann noch lohnt ist natürlich fraglich.

    Ich habe mal im aktuellen GCC Quellcode reingeschaut. Die letzte Änderung an basic_string.h war vor 5 Wochen. Allerdings scheint sich die Implementierung auf den ersten Blick noch nicht C++11-konform zu sein, da const_iterator en einfach so rausgegeben werden, ohne das Sharing vorher aufzuheben.


  • Mod

    Mein letzter Stand (Sommer 2012, daher ist auch meine aktuelle Compilerversion, die ich jetzt nicht aktualisieren werde) ist, dass eine short-string-Optimierung unter dem Namen vstring (ext/vstring.h) enthalten ist. Genauer gesagt ist das ein ganz cleverer String, bei dem man seine Optimierung selber wählen kann. Aber jedenfalls ist die short-string-Optimierung des vstrings die Testimplementierung die später einmal (oder vielleicht auch jetzt schon in der neuesten Version, ich weiß nicht was aktuell ist) die C++11-konforme Implementierung von std::string werden soll.



  • krümelkacker schrieb:

    Danke für das Zitat ... also streng ausgeschlossen wird das jetzt nicht, aber eine ref-counted Implementierung müsste, bevor sie überhaupt Iteratoren oder Referenzen rausgibt, dafür sorgen, dass die Zeichenkette nicht mehr mit anderen string-Objekten geteilt wird. Ob sich das dann noch lohnt ist natürlich fraglich.

    Selbst das ist nicht möglich, denn z.B. begin() ist noexcept , also darf keine Reallokation erfolgen.



  • Deswegen finde ich den fbstring aus der Facebook-Library einfach genial: https://github.com/facebook/folly/blob/master/folly/docs/FBString.md

    Der kombiniert SSO, "normal" allozierte Strings und COW.
    Benutze eigentlich überhaupt keinen std::string mehr bzw ich habe einen Switch in nem Header.

    out schrieb:

    Ethon schrieb:

    Beschreibe im asm-Code einen const char*

    Höö?

    const char* out;
    
    __asm mov edi, out
    
    std::string s(out);
    


  • Ok, damit hat sich das ref-counting bei basic_string wirklich erledigt. Ich bin überzeugt.



  • Ethon schrieb:

    Deswegen finde ich den fbstring aus der Facebook-Library einfach genial: https://github.com/facebook/folly/blob/master/folly/docs/FBString.md

    Der kombiniert SSO, "normal" allozierte Strings und COW.

    Nur kann ich die "100%ige std::string-Kompatibilität" nicht glauben, da ja in C++11, wie ich gelernt habe, begin() z.B. noexcept ist. und FBString::begin ggf eine bad_alloc-Ausnahme schmeißt.


  • Mod

    Die meinen bestimmt 100% kompatibel zu C++98-Strings. Aber dafür in der Praxis schneller als die üblichen Implementierungen.


Anmelden zum Antworten