¿Cuál es la diferencia fundamental, si existe, entre un C++ std :: vector y std :: basic_string?Vector frente a cadena
Respuesta
Un vector es una estructura de datos que simula una matriz. En el fondo es en realidad una matriz (dinámica).
La clase basic_string representa una secuencia de caracteres. Contiene todas las operaciones habituales de una secuencia y, adicionalmente, contiene operaciones de cadena estándar, como búsqueda y concatenación.
Puede usar el vector para guardar cualquier tipo de datos que desee std::vector<int> or <float> or even std::vector< std::vector<T> >
pero basic_string
solo se puede usar para representar "texto".
Estoy seguro de que podría encontrar una manera de hacer que una 'basic_string' esté llena de dobles o algo igualmente malvado y que realmente" funcione ". –
Bueno, la mayoría de las implementaciones implementan 'basic_string' en términos de algo así como' vector'. Y cualquier tipo para el que se define una clase 'char_traits' funcionará con' std :: basic_string', incluso si usted hizo un 'char_traits
@Billy - no es verdadero. Algunas de las mismas técnicas pueden usarse en ambos, pero NUNCA he visto una 'basic_string' implementada en términos de' vector'. De hecho, una implementación muy común, que se distribuye con MSVC++, es MUY diferente ya que utilizan la optimización de cadenas pequeñas (cualquier elemento lo suficientemente pequeño como para caber en un puntero queda atascado en el puntero al almacenamiento intermedio en lugar de asignar uno). –
basic_string proporciona muchas opciones de comparación específicas de cadenas. Tiene razón en que la interfaz de administración de memoria subyacente es muy similar, pero la cadena contiene muchos miembros adicionales, como c_str(), que no tendría sentido para un vector.
No creo que exista un vector que use la optimización de cadenas pequeñas. No he salido a buscar uno, pero estoy bastante seguro de que no está allí. No sería tan útil. La verdad es que las dos cosas son simplemente diferentes. Tienen diferentes propósitos y, por lo tanto, a menudo se implementan MUY diferente, aunque un enfoque ingenuo puede ser similar en ambos. –
@Noah: De ahí por qué dije "interfaz". – Puppy
¿Qué comparaciones son específicas de una cadena? Dado que el tipo de datos del elemento es variable en ambos casos, las cosas como la comparación lexicográfica tienen tanto sentido para los vectores como las cadenas. Por supuesto, una comparación insensible a mayúsculas/minúsculas sería específica de una cadena, pero luego la cadena no sería polimórfica. – Yttrill
La diferencia clave es que std::vector
debe mantener sus datos en la memoria continua, cuando std::basic_string
no pudo. Como resultado:
std::vector<char> v('a', 3);
char* x = &v[0]; // valid
std::basic_string<char> s("aaa");
char* x2 = &s[0]; // doesn't point to continuous buffer
//For example, the behavior of
std::cout << *(x2+1);
//is undefined.
const char* x3 = s.c_str(); // valid
Err .. ese ejemplo de código es perfectamente válido.Ahora bien, si modificó 'x2' utilizando la aritmética del puntero, es posible que no sea válido (dependiendo de su compilador), pero no conozco ningún compilador que lo haga. –
No conozco ese compilador también, pero no debes contar con esos puntos 'x2' para el buffer continuo, porque C++ Standard no da ninguna garantía. –
Ninguno de ellos es válido en realidad. Ninguno de los objetos tiene ningún tamaño y, por lo tanto, el primer elemento es uno pasado y no se puede desreferenciar ese elemento. Solo el c_str() está bien definido. –
basic_string
da compilador y las implementaciones de la biblioteca estándar, unas pocas libertades más vectorial:
La "optimización de la cadena pequeña" es válida en las cuerdas, lo que permite implementaciones para almacenar la cadena real, en lugar de un puntero a la cadena, en el objeto cadena cuando la cadena es corta. Algo a lo largo de las líneas de:
class string { size_t length; union { char * usedWhenStringIsLong; char usedWhenStringIsShort[sizeof(char*)]; }; };
En C++ 03, la matriz subyacente no tiene por qué ser contiguos. Implementar
basic_string
en términos de algo así como una "cuerda" sería posible bajo el estándar actual. (Aunque nadie hace esto porque eso haría que los miembrosstd::basic_string::c_str()
ystd::basic_string::data()
fueran demasiado caros de implementar).
C++ 11 ahora prohíbe este comportamiento.En C++ 03,
basic_string
permite al proveedor del compilador/biblioteca para utilizar la copia en escritura para los datos (que puede ahorrar en las copias), que no está permitido parastd::vector
. En la práctica, esto solía ser mucho más común, pero hoy es menos común debido al impacto que tiene en el multihilo. De cualquier manera, su código no puede depender de si se implementa o nostd::basic_string
utilizando COW.
C++ 11 nuevamente prohíbe este comportamiento.
Hay algunos métodos de ayuda viraron a basic_string
así, pero la mayoría son simples y, por supuesto, podría ser fácilmente implementado en la parte superior de vector
.
No me gusta pensar en (1) como una razón para elegir o usar std :: string es un efecto secundario involuntario de la redacción estándar que se ha ajustado en el nuevo estándar. (2) fue una buena razón para usar std :: string ya que hizo que devolver cadenas de métodos muy eficientes (prácticamente sin costo) lamentablemente se está eliminando debido a los requisitos de paralelismo (aunque al leer el documento que recomienda esto, parece que la cuerda ocupará ese manto de COW con el tiempo (tendremos que esperar y ver si esto funciona). –
@Martin: Esto es cierto. La semántica del movimiento OTOH elimina a MUCHOS de los casos en que las implementaciones COW aceleraron las cosas :) –
basic_string no llama a constructores y destructores de sus elementos. vector hace.
swapping basic_string invalida iteradores (permitiendo la optimización de cadenas pequeñas), intercambiando vectores no.
basic_string la memoria no se puede asignar continuamente en C++ 03. el vector es siempre continuo. Esta diferencia se elimina en C++ 0x [string.require]:
Los objetos de char-como en un objeto basic_string serán almacenados de forma contigua
basic_string tiene interfaz para operaciones de cadenas. el vector no.
basic_string puede usar copiar en la estrategia de escritura (en pre C++ 11). el vector no puede
citas relevantes para los no creyentes:
[basic.string]:
El basic_string plantilla de clase se ajusta a los requisitos de un contenedor de secuencias (23.2.3), para una Contenedor reversible (23.2), y para un contenedor compatible con Allocator (Tabla 99), excepto que basic_string no construye ni destruye sus elementos utilizando allocator_traits :: construc y allocator_- rasgos :: destroy y ese swap() para basic_string invalida iteradores. Los iteradores compatibles con por basic_string son iteradores de acceso aleatorio (24.2.7).
@Billy: lea el estándar antes de downvoting, he agregado la cita. – ybungalobill
Por lo que puedo decir, esa cita no es de 'la norma' sino del borrador de C++ 0x. Está bien y vale la pena mencionarlo, pero debe calificarlo con "En C++ 0x ...". – GManNickG
@GMan: Hmm, parece que tienes razón. Pero solo la formulación es diferente, C++ 98 todavía dice que solo asigna y desasigna los elementos. Este cambio es solo una aclaración. – ybungalobill
Una diferencia entre std::string
y std::vector
es que los programas pueden construir una cadena de una cadena terminada en nulo, mientras que con los vectores que no pueden.
std::string a = "hello"; // okay
std::vector<char> b = "goodbye"; // compiler error
Esto a menudo hace que las cadenas sean más fáciles de trabajar.
TLDR: string
s están optimizados para contener sólo las primitivas de caracteres, vector
s pueden contener primitivas o objetos
La diferencia preeminente entre vector
y string
es que vector
pueden contener correctamente objetos, string
sólo funciona en primitivas. Así vector
proporciona estos métodos que serían inútiles para un string
trabajar con elementos:
Incluso se extiende string
no permitirá que le permite manejar correctamente los objetos, porque carece de un destructor.Esto no debe ser visto como una desventaja, que permite la optimización significativa sobre vector
en que string
puede:
- Haz short string optimization, evitando potencialmente asignación del montón, con little-no increased storage overhead
- Uso
char_traits
, uno de plantillastring
's argumentos, para definir cómo las operaciones se deben implementar en las primitivas de contenidos (de los cuales sólochar
,wchar_t
,char16_t
, ychar32_t
se implementan: http://en.cppreference.com/w/cpp/string/char_traits)
Particularmente relevantes son char_traits::copy
, char_traits::move
y char_traits::assign
, lo que obviamente implica que se utilizará la asignación directa, en lugar de la construcción o destrucción, que es nuevamente preferible para los primitivos. Toda esta especialización tiene los inconvenientes adicionales a string
que:
- Sólo
char
, se utilizaráwchar_t
,char16_t
ochar32_t
tipos primitivos. Obviamente, las primitivas de tamaños de hasta 32 bits, podrían utilizar su tamaño equivalentechar_type
: https://stackoverflow.com/a/35555016/2642059, pero para las primitivas tales comolong long
tendría que ser escrito una nueva especialización dechar_traits
, y la idea de especializarsechar_traits::eof
ychar_traits::not_eof
en lugar de sólo usarvector<long long>
no parece ser el mejor uso del tiempo. - Debido a la optimización de cadena corta, iteradores son invalidadas por todas las operaciones que pudieran invalidar un iterador
vector
, perostring
iteradores son, además, invalidado porstring::swap
ystring::operator=
diferencias adicionales en las interfaces de vector
y string
:
- no hay mutable
string::data
: Why Doesn't std::string.data() provide a mutable char*? string
proporciona funcionalidad para trabajar con palabras no disponibles envector
:string::c_str
,string::length
,string::append
,string::operator+=
,string::compare
,string::replace
,string::substr
,string::copy
,string::find
,string::rfind
,string::find_first_of
,string::find_first_not_of
,string::flind_last_of
,string::find_last_not_of
,string::operator+
,string::operator>>
,string::operator<<
,string::stoi
,string::stol
,string::stoll
,string::stoul
,string::stoull
,string::stof
,string::stod
,string::stold
,stirng::to_string
,string::to_wstring
- Finalmente todas partes
vector
acepta los argumentos de otravector
,string
acepta unstring
o unchar*
Nota esta respuesta está escrito en C++ 11 en contra, por lo que se requieren string
s que se asignarán de forma contigua.
- 1. vector STL frente a borrado de mapa
- 2. Vector claro frente a cambiar el tamaño
- 3. iterador frente a referencia frente a puntero
- 4. Encriptación: ¿uso del vector de inicialización frente a la clave?
- 5. Vector frente a marco de datos en R
- 6. Conversión de un vector a cadena
- 7. cadena c_str() frente a los datos()
- 8. cadena de bytes frente a cadena unicode. Python
- 9. NUnit frente a MbUnit frente a MSTest frente a xUnit.net
- 10. Herencia frente a la especialización
- 11. vector <char> a fallo de segmentación de cadena
- 12. C++: stringstream a vector
- 13. tipo de cadena .NET frente a la matriz de caracteres
- 14. arrays de C# - string [] [] frente a la cadena [,]
- 15. Uso de decode() frente a regex para deshacer esta cadena
- 16. ¿por qué usar constantes de cadena frente a constantes enum?
- 17. Literales de cadena frente a const char * en C
- 18. Delphi 2010 Funciones amplias frente a funciones de cadena
- 19. Cadena frente a una nueva clase de datos
- 20. Tabla de búsqueda frente a if-else
- 21. Borrado vector :: final a partir del vector
- 22. optimización de cadena pequeña para vector?
- 23. Dividir un vector de cadena en R
- 24. Página frente a extensión frente a segmento frente a espacio de tabla
- 25. Terminología de persistencia de objetos: 'repositorio' frente a 'almacenar' frente a 'contexto' frente a 'retriever' vs. (...)
- 26. ¿Por qué esto es tan lento? (bucle en una fila DF frente a un vector independiente)
- 27. C++: vector a stringstream
- 28. Puntero a un Vector
- 29. Imagen frente a foto frente a imagen - Modelos de nomenclatura
- 30. Desarrollo de iPhone - XMLParser frente a libxml2 frente a TouchXML
Compruebe los documentos, tienen diferentes interfaces. Si especificó el problema real que está resolviendo, las respuestas también podrían haber sido más específicas. –
@Gene: Tienen diferentes interfaces, pero ambas implementan todo lo necesario para ser un contenedor de secuencia STL. –
@Gene: No estoy resolviendo ningún problema en particular, solo tengo curiosidad sobre por qué debería elegir uno u otro para varios propósitos: no estoy contando la existencia de algunos métodos adicionales de cadenas como fundamentales. Realmente no cuento el rendimiento como fundamental tampoco. Sin embargo, la validez de los iteradores es la respuesta a varias respuestas. Y tengo una vaga sospecha de que el tipo de datos para una cadena debe tener un valor de "Cero como" para poner al final del método data() (obtenido de una característica de los rasgos). – Yttrill