versiones dev compiler c++ standards c++11

dev - c++17



¿Por qué std:: vector:: data y std:: string:: data son diferentes? (4)

@Christian Rau

Desde el momento en que la clase Plauger original (alrededor de 1995 creo) fue STL -ized por el comité (convertida en una secuencia, templatificada), std::string siempre ha sido std::vector más cosas relacionadas con cadenas (conversión de / to 0-endedted, concatenation, ...), más algunas rarezas, como COW que en realidad es " Copy on Write y on no const begin() / end() / operator[] ".

Pero en última instancia, std::string es realmente un std::vector bajo otro nombre, con un enfoque e intención ligeramente diferentes. Asi que:

  • al igual que std::vector , std::string tiene un miembro de datos de tamaño o ambos miembros de datos de inicio y final;
  • al igual que std::vector , std::string no se preocupa por el valor de sus elementos, NUL incrustado u otros.

std::string no es una cadena C con sintaxis azucarada, funciones de utilidad y algo de encapsulamiento, al igual que std::vector<T> no es T[] con sintaxis azucarada, funciones de utilidad y alguna encapsulación.

Los nuevos data() métodos de Vector data() proporcionan una versión const y non-const.
Sin embargo, el método data() string solo proporciona una versión const.

Creo que cambiaron la redacción sobre std::string por lo que ahora se requiere que los caracteres sean contiguos (como std::vector ).

¿Se perdió std::string::data ? ¿O es una buena razón para permitir solo el acceso const a los caracteres subyacentes de una cadena?

Nota: std::vector::data tiene otra característica agradable, no es un comportamiento indefinido llamar a data() en un vector vacío. Mientras que &vec.front() es un comportamiento indefinido si está vacío.


Aunque no soy tan versado en el estándar, podría deberse al hecho de que std::string no necesita contener datos terminados en nulo, pero puede y no necesita contener una longitud explícita. campo, pero puede. Por lo tanto, cambiar los datos de undelying y, por ejemplo, agregar un ''/0'' en el medio podría hacer que el campo de longitud de cadenas no esté sincronizado con los datos de char reales y así dejar el objeto en un estado no válido.


En C ++ 98/03 hubo una buena razón para no tener data() no const data() debido al hecho de que la cadena a menudo se implementaba como COW. Un data() no const data() habría requerido una copia si el recuento fuera mayor que 1. Mientras sea posible, esto no se consideró deseable en C ++ 98/03.

En octubre de 2005, el comité votó en LWG 464, que agregó los datos const y non-const data() al vector , y agregó const y non-const at() al map . En ese momento, la string no había sido cambiada para proscribir a COW. Pero más tarde, mediante C ++ 11, una string COW ya no se ajusta. La especificación de string también se ajustó en C ++ 11 de modo que se requiere que sea contigua, y siempre hay un nulo de terminación expuesto por el operator[](size()) . En C ++ 03, el nulo de terminación solo estaba garantizado por la sobrecarga const del operator[] .

En resumen, una información no const data() parece mucho más razonable para una string C ++ 11. Hasta donde yo sé, nunca fue propuesto.

Actualizar

charT* data() noexcept;

se agregó basic_string en el borrador de trabajo C ++ 1z N4582 de P0272R1 de David Sankel en la reunión de Jacksonville en febrero de 2016.

Buen trabajo David!


Históricamente, los datos de cadena no han sido const porque evitarían varias optimizaciones comunes, como copy-on-write (COW). Esto es ahora, IIANM, mucho menos común, porque se comporta mal con programas multiproceso.

Por cierto, sí, ahora se requiere que sean contiguos:

[string.require] .5: los objetos de tipo char en un objeto basic_string se almacenarán contiguamente. 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 ().

Otra razón podría ser evitar un código como:

std::string ret; strcpy(ret.data(), "whatthe...");

O cualquier otra función que devuelva una matriz de caracteres preasignada.