std::string - modifizieren über &str[0] OK?



  • Ryuzaki schrieb:

    drakon schrieb:

    23.1.1/1 schrieb:

    A sequence is a kind of container that organizes a finite set of objects, all of the same type, into a strictly
    linear arrangement. The library provides three basic kinds of sequence containers: vector, list, and
    deque.[...]

    Da wird ja indirekt sogar ein Bezug zu std::vector gemacht.

    Da steht auch list, und da liegt garantiert nichts hintereinander im Speicher.
    Ich hab vorhin auch mal im Standard gesucht und keine Garantie gefunden. Und wenn ich mich recht erinnere wurde hier im Forum schonmal darauf hingewiesen, dass man sich nicht darauf verlassen kann, dass das hintereinander im Speicher liegt.

    Stimmt. Da habe ich vorschnell das linear falsch gedeutet.



  • Ryuzaki schrieb:

    Da steht auch list, und da liegt garantiert nichts hintereinander im Speicher.

    Garantiert der Standard etwa, das bei std::list nichts hintereinander liegt? 😉



  • daersc schrieb:

    Ryuzaki schrieb:

    Da steht auch list, und da liegt garantiert nichts hintereinander im Speicher.

    Garantiert der Standard etwa, das bei std::list nichts hintereinander liegt? 😉

    Ja, indirekt. Nämlich durch die complexity-bounds diverser Operationen wie splice().



  • David_pb schrieb:

    21.3.4/1 schrieb:

    Returns: If pos < size(), returns data()[pos]. Otherwise, if pos == size(), the const
    version returns charT(). Otherwise, the behavior is undefined.

    und

    21.3.6/3/4 schrieb:

    Returns: If size() is nonzero, the member returns a pointer to the initial element of an array whose first
    size() elements equal the corresponding elements of the string controlled by *this. If size() is
    zero, the member returns a non-null pointer that is copyable and can have zero added to it.
    4 Requires: The program shall not alter any of the values stored in the character array. Nor shall the program
    treat the returned value as a valid pointer value after any subsequent call to a non- const member
    function of basic_string that designates the same object as this.

    Aber: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530

    Also wenn ich das richtig verstehe, dann kann ich getrost str.data() verwenden um in einen String "reinzumalen" - mittels memcpy() oder was auch immer.

    Vorausgesetzt natürlich dass der String gross genug ist.

    Ob die Adresse die ich über das Iterator-Interface bekomme auch die selbe ist, ist mir ziemlich egal. Ich muss das Iterator-Interface ja nicht verwenden.


  • Mod

    hustbaer schrieb:

    Also wenn ich das richtig verstehe, dann kann ich getrost str.data() verwenden um in einen String "reinzumalen" - mittels memcpy() oder was auch immer.

    Nein, da data einen Zeiger auf konstantes charT liefert. Spätestens bei einer COW-Implementierung dürfte es Probleme geben.
    &*begin() oder &at(0) etc. sind dagegen unproblematisch.



  • Jain, in 21.3.6/4 steht ganz zu beginn: The program shall not alter any of the values stored in the character array und da operator[] auf data() basiert gilt das für diesen wohl auch.

    Aufgrund http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530 funktioniert das wohl trotzdem mit allen möglichen Implementierungen von basic_string. Allerdings ist das wohl nicht durch den Standard definiert.

    In C++0x gibts da glaub ich dann eine Klausel die das garantiert. 🙂


  • Mod

    David_pb schrieb:

    Jain, in 21.3.6/4 steht ganz zu beginn: The program shall not alter any of the values stored in the character array und da operator[] auf data() basiert gilt das für diesen wohl auch.

    Aufgrund http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530 funktioniert das wohl trotzdem mit allen möglichen Implementierungen von basic_string. Allerdings ist das wohl nicht durch den Standard definiert.

    In C++0x gibts da glaub ich dann eine Klausel die das garantiert. 🙂

    Nicht ganz basic_string::operator[] and const correctness



  • Er, ja, da ich data() nie verwende, wusste ich nicht, dass es davon keine non-const Variante gibt. Const wegcasten werde ich natürlich nicht.

    Ich denke ich werde einfach &at(0) bzw. &[0] verwenden.



  • daersc schrieb:

    Garantiert der Standard etwa, das bei std::list nichts hintereinander liegt? 😉

    Ja, indirekt durch die Anforderungen an die Zeitkomplexität der Operationen.

    hustbaer schrieb:

    Ich denke ich werde einfach &at(0) bzw. &[0] verwenden.

    Blöd ist nur, wenn du (oder sonst jemand) den Code portiert und dann nicht mehr daran denkt, und plötzlich hat man merkwürdige Bugs. Vielleicht kannst du ja eine Assertion schreiben, à la

    char* string_data(std::string& str)
    {
       assert(&str[str.size()-1] - &str[0] == static_cast<ptrdiff_t>(str.size()-1));
       return &str[0];
    }
    

    Die Subtraktion erzeugt zwar undefiniertes Verhalten, wenn die beiden Zeiger nicht im gleichen Array stehen, aber sowas dürfte meiner Ansicht nach noch eher toleriert werden (und falls nicht, hat man auch nichts verloren).

    Ist nur so ein Vorschlag. Wenn du den Code nie portieren wirst und dir sicher bist, dass sich deine StdLib-Implementierung nicht ändert, ist das natürlich unnötig.



  • Ja mal sehen.
    Lustigerweise funktioniert es sogar mit der COW Implementierung vom VC6.
    Sogar die erzwingt bei at() und [] (und begin/end/rbegin/rend) korrekterweise dass der String eindeutig gemacht wird.


Anmelden zum Antworten