¿"&s[0]" apunta a caracteres contiguos en una cadena std::?

Resuelto oz10 asked hace 14 años • 6 respuestas

Estoy haciendo algunos trabajos de mantenimiento y me encontré con algo como lo siguiente:

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 );

Sé que usar &s[0] sería seguro si fuera un std::vector, pero ¿es este un uso seguro de std::string?

oz10 avatar Jan 01 '10 03:01 oz10
Aceptado

No se garantiza que la asignación de una std::string sea contigua según el estándar C++ 98/03, pero C++ 11 obliga a que lo sea. En la práctica, ni Herb Sutter ni yo conocemos ninguna implementación que no utilice almacenamiento contiguo.

Tenga en cuenta que &s[0]siempre se garantiza que la cosa funcione según el estándar C++ 11, incluso en el caso de cadena de longitud 0. No estaría garantizado si lo hiciera str.begin()o &*str.begin(), pero &s[0]el estándar lo define operator[]como:

Devuelve : *(begin() + pos)if pos < size(), en caso contrario una referencia a un objeto de tipo Tcon valor charT(); el valor referenciado no será modificado

Continuando, data()se define como:

Devuelve: Un puntero ptal que p + i == &operator[](i)para cada uno ien [0,size()].

(observe los corchetes en ambos extremos del rango)


Aviso : C++ 0x previo a la estandarización no garantizaba &s[0]el funcionamiento con cadenas de longitud cero (en realidad, era un comportamiento explícitamente indefinido), y una revisión anterior de esta respuesta explicaba esto; Esto se solucionó en borradores estándar posteriores, por lo que la respuesta se actualizó en consecuencia.

Todd Gardner avatar Dec 31 '2009 20:12 Todd Gardner

Es seguro de usar. Creo que la mayoría de las respuestas fueron correctas una vez, pero el estándar cambió. Citando el estándar C++ 11, requisitos generales basic_string [string.require] , 21.4.1.5, dice:

Los objetos tipo char en un objeto basic_string se almacenarán de forma contigua. Es decir, para cualquier objeto basic_string s, la identidad &*(s.begin() + n) == &*s.begin() + n se mantendrá para todos los valores de n tales que 0 <= n < s.size ().

Un poco antes de eso, dice que todos los iteradores son iteradores de acceso aleatorio. Ambos bits respaldan el uso de su pregunta. (Además, Stroustrup aparentemente lo usa en su libro más reciente;))

No es improbable que este cambio se haya realizado en C++11. Creo recordar que se agregó la misma garantía para vector, que también obtuvo el puntero data() muy útil con esa versión.

Espero que ayude.

sebkraemer avatar Jan 19 '2015 12:01 sebkraemer

Técnicamente no, ya que std::stringno es necesario almacenar su contenido de forma contigua en la memoria.

Sin embargo, en casi todas las implementaciones (todas las implementaciones que conozco), los contenidos se almacenan de forma contigua y esto "funcionaría".

James McNellis avatar Dec 31 '2009 20:12 James McNellis