Frage

Ich mache einige Wartungsarbeiten und läuft über etwa wie folgt:

std::string s;
s.resize( strLength );  
// strLength is a size_t with the length of a C string in it. 

memcpy( &s[0], str, strLength );

Ich weiß mit & s [0] wäre sicher, wenn es sich um ein std :: vector war, aber das ist eine sichere Verwendung von std :: string?

War es hilfreich?

Lösung

A std :: string der Zuordnung ist nicht zusammenhängend unter dem C sein garantiert ++ 98/03-Standard, aber C ++ 11 Kräfte zu sein. In der Praxis weder ich noch Herb Sutter weiß von einer Implementierung, die nicht zusammenhängende Speicher nicht verwendet.

Beachten Sie, dass die &s[0] Sache immer auf der Arbeit von der C ++ 11-Standard gewährleistet ist, auch in dem 0-Zeichenfolge Fall. Es wäre nicht gewährleistet, wenn Sie str.begin() oder &*str.begin() tun, aber für &s[0] der Standard definiert operator[] wie:

  

Returns : *(begin() + pos) wenn pos < size(), ansonsten eine Referenz auf ein Objekt vom Typ T mit Wert charT(); der referenzierte Wert darf nicht verändert werden

Weiter auf, data() ist wie folgt definiert:

  

Returns:. Ein Zeiger p so dass p + i == &operator[](i) für jede i in [0,size()]

(man beachte die eckigen Klammern an beiden Enden des Bereichs)


Hinweis : Vornormenbereich C ++ 0x hat nicht Garantie &s[0] zur Arbeit mit der Länge Null Saiten (eigentlich war es ausdrücklich nicht definiertes Verhalten) und eine ältere Version dieser Antwort erklärte dies; dies hat in späteren Standardentwürfen fest, so dass die Antwort entsprechend aktualisiert wurde.

Andere Tipps

Technisch, nein, da std::string nicht erforderlich seinen Inhalt im Speicher zusammenhängend zu speichern.

Doch in fast allen Implementierungen (jede Implementierung von denen ich bin mir bewusst), wird der Inhalt gespeichert aneinander angrenzend und dies würde „zu arbeiten.“

Es ist sicher zu bedienen. Ich denke, die meisten Antworten waren richtig einmal, aber der Standard geändert. Zitiert von C ++ 11-Standard, basic_string allgemeine Anforderungen [string.require] , 21.4.1.5, sagt:

  

Die kohleartige Objekte in einem basic_string Objekt werden zusammenhängend gespeichert werden. Das heißt, für jeden basic_string   Objekt s, die Identität & * (s.begin () + n) == & * s.begin () + n gilt für alle Werte von n, so daß 0 halten   <= N

Ein bisschen davor, heißt es, dass alle Iteratoren sind Random Access-Iteratoren. Beide Bits unterstützen die Nutzung Ihrer Frage. (Zusätzlich Stroustrup offenbar verwendet es in seinem neuesten Buch;))

Es ist nicht unwahrscheinlich, dass diese Änderung in C ++ 11 durchgeführt wurde. Ich glaube mich zu erinnern, dass die gleiche Garantie wurde dann für Vektor hinzugefügt, das bekam auch die sehr nützlich Daten () Zeiger mit diesem Release.

Ich hoffe, das hilft.

Die Leser werden darauf hingewiesen, dass diese Frage im Jahr 2009 gefragt wurde, wenn der C ++ 03 Standard-die aktuelle Veröffentlichung war. Diese Antwort wird auf der Grundlage dieser Version des Standards, in denen std::strings sind nicht garantiert sequenziellen Speicher zu nutzen. Da diese Frage nicht im Zusammenhang mit einer bestimmten Plattform (wie gcc) gefragt wurde, mache ich keine Annahmen über OP-Plattform - insbesondere, Wetter oder nicht contigious Speicher für die string verwendet

.

Legal? Vielleicht, vielleicht nicht. Sicher? Wahrscheinlich, aber vielleicht auch nicht. Guter Code? Nun, lassen Sie uns nicht dorthin gehen ...

Warum nicht einfach tun:

std::string s = str;

... oder:

std::string s(str);

... oder:

std::string s;
std::copy( &str[0], &str[strLen], std::back_inserter(s));

... oder:

std::string s;
s.assign( str, strLen );

Der Code könnte funktionieren, aber mehr durch Glück als Verstand, macht es Annahmen über die Implementierung, die nicht garantiert ist. Ich schlage vor, die Bestimmung der Gültigkeit des Codes keine Rolle spielt, während es eine sinnlose über Komplikation ist, die leicht auf nur reduziert:

std::string s( str ) ;

oder wenn die Zuordnung zu einem bestehenden std :: string-Objekt, nur:

s = str ;

und dann lassen Sie std :: string selbst bestimmen, wie das Ergebnis zu erzielen. Wenn Sie auf diese Art von Unsinn greifen wollen, dann können Sie auch nicht std :: string und Stick zu verwenden, da Sie alle die Gefahren im Zusammenhang mit C-Strings sind wieder einzuführen.

Dies ist im Allgemeinen nicht sicher, unabhängig davon, ob die interne String-Sequenz kontinuierlich im Speicher gespeichert ist oder nicht. Es gibt viele anderen Implementierungsdetails in Bezug auf sein könnte, wie die kontrollierte Sequenz von std::string Objekt gespeichert ist, neben der Kontinuität.

Ein echtes praktisches Problem mit, dass könnte die folgende sein. Die gesteuerte Sequenz von std::string nicht erforderlich ist als Null endende Zeichenfolge gespeichert werden. Doch in der Praxis entscheiden sich viele (die meisten?) Implementierungen der internen Puffer von 1 und speichern Sie die Sequenz als eine Null-terminierten String sowieso Aufmaß, weil sie die Umsetzung der c_str() Verfahren vereinfacht: nur einen Zeiger auf den internen Puffer zurück, und Sie sind getan.

Der Code, den Sie in Ihrer Frage zitierten keine Anstrengungen unternehmen, um Null-kündigt die Daten in den internen Puffer kopiert werden. Durchaus möglich einfach ist es nicht wissen, ob Null-Terminierung für diese Implementierung von std::string notwendig ist. Durchaus möglich stützt sie sich auf den internen Puffer mit Nullen nach dem Aufruf von resize gefüllt wird, so dass die zusätzliche Zeichen zugeordnet für die Null Terminator durch die Implementierung bequem auf Null-Set vor. All dies ist eine Implementierung Detail, was bedeutet, dass diese Technik auf einigen ziemlich zerbrechlich Annahmen abhängt.

Mit anderen Worten, in einigen Implementierungen, dann würden Sie wahrscheinlich zu verwenden strcpy haben, nicht memcpy so die Daten in die kontrollierten Sequenz zu erzwingen. Während in einigen anderen Implementierungen würden Sie haben memcpy und nicht strcpy zu verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top