Implementation der c_str()-Funktion?



  • Hi, mal angenommen ich habe eine String-Klasse in der ich alle Zeichen nicht null-terminiert in einem Vector speichere.
    Wie würde man nun eine Funktion implementieren die einen wchar_t* zurückgibt?
    Beim std::string wird ein dynamisches Array erstellt und mit Kopien der Zeichen plus angehängtes '\0' zurückgegeben. Allerdings weis ich nicht wie man dann dafür sorgen kann dass dieser C-String auch wieder freigegeben wird. Jemand eine Idee? Evtl. Smartpointer?



  • Ich denke nicht, daß die string::c_str()-Methode den Speicher kopiert - sie reserviert nur genug Speicher für den zusätzlichen Null-Terminator und arbeitet nach dem Aufruf mit diesem Speicher weiter. (wobei string sich sowieso etwas Luft nach oben lässt - siehe reserve()/capacity())



  • @ CStoll:

    Ich denke nicht, daß die string::c_str()-Methode den Speicher kopiert

    Hast recht mit deinem Denken 😉

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
        string cpp = "Hallo Welt.";
        char* c = const_cast<char *>(cpp.c_str());
        cout << cpp << endl << c << endl << endl; // Hallo Welt.   Hallo Welt.
        *(c + 2) = 'x';
        cout << cpp << endl << c << endl << endl; // Haxlo Welt.   Haxlo Welt.
        return 0;
    }
    

    Ruft man allerdings vorher "reserve" auf, wird der C-String vom C++-String getrennt. Ist ja auch logisch 🙂



  • Achso, ich hatte das zumindest hier so rausgelesen:
    http://www.cplusplus.com/reference/string/string/c_str/
    Aber du hast recht. Ich brauche ja nur dafür zu sorgen, dass die Capacity mindestens ein Zeichen größer als die Size ist und diesem reservierten Zeichen dann den Wert '\0' zuordnen.
    Allerdings könnte das großen Murks geben wenn dieser String verändert würde und weiterhin ein Pointer auf den Inhalt zeigt. Aber das ist beim std::string wenn ich den Artikel oben richtig interpretiere auch nicht anders.



  • Wurstinator schrieb:

    Ruft man allerdings vorher "reserve" auf, wird der C-String vom C++-String getrennt. Ist ja auch logisch 🙂

    Schlimmer - beim reserve werden bestehende Verweise in die String-Inhalte (inklusive des von c_str() zurückgelieferten Zeigers) ungültig - wenn du dann noch darauf zugreifst, ergibt das undefiniertes Verhalten.

    @Fine: Für die Fälle, wo du das logisch trennen willst, gibt es auch string::copy() - und da ist der Anwender dafür verantwortlich, genug Speicher bereitzustellen (und wieder aufzuräumen).



  • Ich denke die üblichen std::string Implementierungen werden so gebaut sein, dass sie den String immer Nullterminiert bereithalten.
    c_str() macht in dem Fall genau gar nix, ausser den Zeiger auf den aktuellen String-Inhalt zurückzugeben.


Anmelden zum Antworten