Dejemos de lado la posibilidad de que *d
no es válido, ya que no tiene nada que ver con lo que la pregunta parece estar dirigido a: si o no std::string operator[]()
tiene un comportamiento bien definido cuando se accede al "elemento" en el índice std::string::size()
.
El estándar de C++ 03 tiene la siguiente descripción de string::operator[]()
(21.3.4 "basic_string
acceso elemento"):
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
devoluciones: Si pos < size()
, devuelve data()[pos]
. De lo contrario, si pos == size()
, la versión const devuelve charT()
. De lo contrario, el comportamiento no está definido.
Desde s
en el código de ejemplo es const
, el comportamiento está bien definido y s[s.size()]
devolverá un carácter nulo.Sin embargo, si s
no era const string
, el comportamiento sería indefinido.
C++ 11 soluciona este comportamiento extraño de la versión const
que se comporta de manera tan diferente a la versión no const en este caso de borde. C++ 11 21.4.5 "basic_string
acceso elemento" dice:
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
Requiere: pos <= size()
.
Devuelve: *(begin() + pos
) si es pos < size()
, de lo contrario, una referencia a un objeto de tipo T con valor charT()
; el valor referenciado no se modificará.
Así que para un compilador de C++ 11, el comportamiento está bien definido si el string
es const
.
No relacionado con la pregunta, me parece un poco extraño que C++ 11 diga que "el valor al que se hace referencia no se modificará" - no me queda claro si esa cláusula se aplica solo en el caso donde pos == size()
. Estoy bastante seguro de que hay una tonelada de código existente que hace cosas como s[i] = some_character;
donde s
es un no-const std:string
y i < s.size()
. ¿Es ese comportamiento indefinido ahora? Sospecho que esa cláusula se aplica solo al objeto de caso especial charT()
.
Otra cosa interesante es que ninguno de los estándares parece requerir que la dirección del objeto devuelto para s[s.size()]
esté relacionada de algún modo con la dirección del objeto devuelto para s[s.size() - 1]
. En otras palabras, parece que la referencia charT()
devuelta no tiene que ser contigua al final de los datos de cadena. Sospecho que esto es para darles a los implementadores la opción de simplemente devolver una referencia a una única copia estática de ese elemento centinela si así lo desean (eso también explicaría la restricción "no se modificará" de C++ 11, asumiendo que se aplica solo al especial caso).
Estaría más preocupado por el puntero de destino. ¿Por qué esa función no toma un parámetro de tamaño? – LaC
Quizás debería intentar copiar 's.c_str()' si quiere tener el terminador nulo en la copia ... – Yaniro
tal vez 'd' tiene una capacidad incorrecta – Abyx