Diferencia entre los tipos string y char en C ++

Sé un poco de C y ahora estoy mirando C ++. Estoy acostumbrado a las matrices de caracteres para tratar cadenas de C, pero mientras miro el código de C ++ veo que hay ejemplos que usan tanto tipo de cadena como matrices de caracteres:

#include  #include  using namespace std; int main () { string mystr; cout << "What's your name? "; getline (cin, mystr); cout << "Hello " << mystr << ".\n"; cout << "What is your favorite team? "; getline (cin, mystr); cout << "I like " << mystr << " too!\n"; return 0; } 

y

 #include  using namespace std; int main () { char name[256], title[256]; cout << "Enter your name: "; cin.getline (name,256); cout << "Enter your favourite movie: "; cin.getline (title,256); cout << name << "'s favourite movie is " << title; return 0; } 

(ambos ejemplos de http://www.cplusplus.com )

Supongo que esta es una pregunta ampliamente formulada y respondida (¿obvio?), Pero sería bueno si alguien pudiera decirme cuál es exactamente la diferencia entre esas dos formas de tratar cadenas en C ++ (rendimiento, integración de API, la forma en que cada uno es mejor, …).

Gracias.

Una matriz char es solo eso: una matriz de caracteres:

  • Si está asignado en la stack (como en su ejemplo), siempre ocupará, por ejemplo. 256 bytes sin importar cuánto tiempo el texto contiene
  • Si se asigna en el montón (usando malloc () o nuevo char []), usted es responsable de liberar la memoria después y siempre tendrá la sobrecarga de una asignación de montón.
  • Si copia un texto de más de 256 caracteres en la matriz, podría colapsar, producir mensajes de aserción desagradables o causar un comportamiento (inexistente) inexplicable en otro lugar de su progtwig.
  • Para determinar la longitud del texto, la matriz debe escanearse, carácter por carácter, para un carácter \ 0.

Una cadena es una clase que contiene una matriz de caracteres, pero la administra automáticamente. La mayoría de las implementaciones de cadenas tienen una matriz integrada de 16 caracteres (por lo que las cadenas cortas no fragmentan el montón) y usan el montón para cadenas más largas.

Puede acceder a la matriz char de una cadena como esta:

 std::string myString = "Hello World"; const char *myStringChars = myString.c_str(); 

Las cadenas de C ++ pueden contener caracteres \ 0 incrustados, saber su longitud sin contar, son más rápidas que las matrices de caracteres asignadas en el montón para textos breves y te protegen de los desbordamientos del búfer. Además, son más legibles y fáciles de usar.

Sin embargo, las cadenas de C ++ no son (muy) adecuadas para usar en límites de DLL, ya que esto requeriría que cualquier usuario de dicha función DLL se asegure de estar usando el mismo comstackdor y la misma implementación en tiempo de ejecución de C ++, para que no corra el riesgo de que su clase de cadena se comporte de manera diferente.

Normalmente, una clase de cadena también liberaría su memoria de stack en el montón de llamadas, por lo que solo podrá liberar memoria de nuevo si está utilizando una versión compartida (.dll o .so) del tiempo de ejecución.

En resumen: use cadenas de C ++ en todas sus funciones y métodos internos. Si alguna vez escribe un .dll o .so, use C strings en sus funciones públicas (dll / so-exposed).

Bueno, el tipo de cadena es una clase completamente administrada para cadenas de caracteres, mientras que char [] sigue siendo lo que era en C, una matriz de bytes que representa una cadena de caracteres para ti.

En términos de API y biblioteca estándar, todo se implementa en términos de cadenas y no de char [], pero todavía hay muchas funciones de la libc que reciben char [], por lo que es posible que tenga que usarlo para esas, aparte de eso, lo haría siempre use std :: string.

En términos de eficiencia, por supuesto, un buffer crudo de memoria no administrada casi siempre será más rápido para muchas cosas, pero tenga en cuenta la comparación de cadenas, por ejemplo, std :: string siempre tiene el tamaño para verificarlo primero, mientras que con char [] usted Necesito comparar personaje por personaje.

Arkaitz tiene razón en que la string es un tipo administrado. Lo que esto significa para usted es que nunca tiene que preocuparse por cuánto tiempo es la cadena, ni tiene que preocuparse por liberar o reasignar la memoria de la cadena.

Por otro lado, la notación char[] en el caso anterior ha restringido el búfer de caracteres a exactamente 256 caracteres. Si trataste de escribir más de 256 caracteres en ese búfer, en el mejor de los casos sobrescribirás otra memoria que tu progtwig “posee”. En el peor de los casos, intentará sobrescribir la memoria que no posee, y su sistema operativo matará su progtwig en el acto.

¿Línea de fondo? Las cadenas son mucho más amigables con los progtwigdores, las [char] son ​​mucho más eficientes para la computadora.

Personalmente, no veo ninguna razón por la cual uno quiera usar char * o char [] excepto por compatibilidad con el código anterior. std :: string no es más lento que usar una cadena de caracteres, excepto que manejará la reasignación por usted. Puede establecer su tamaño cuando lo crea, y así evitar la reasignación si lo desea. Su operador de indexación ([]) proporciona acceso de tiempo constante (y en todo el sentido de la palabra es exactamente lo mismo que usar un indexador de cadena de caracteres). El uso del método at también te da seguridad en los límites comprobados, algo que no obtienes con c-strings, a menos que lo escribas. Su comstackdor optimizará con mayor frecuencia el uso del indexador en el modo de lanzamiento. Es fácil perder el tiempo con c-strings; cosas como eliminar frente a eliminar [], seguridad de excepción, incluso cómo reasignar una cadena de caracteres.

Y cuando tenga que lidiar con conceptos avanzados como tener cadenas COW, y no COW para MT, etc., necesitará std :: string.

Si le preocupan las copias, siempre que utilice referencias y referencias contínuas siempre que pueda, no tendrá ningún sobrecarga debido a las copias, y es lo mismo que haría con la cadena de caracteres.

Las cadenas tienen funciones de ayuda y administran las matrices de caracteres automáticamente. Puede concatenar cadenas, para una matriz de caracteres que necesitaría copiar a una nueva matriz, las cadenas pueden cambiar su longitud en tiempo de ejecución. Una matriz char es más difícil de administrar que una cadena y ciertas funciones solo pueden aceptar una cadena como entrada, lo que requiere que convierta la matriz en una cadena. Es mejor usar cadenas, fueron hechas para que no tengas que usar matrices. Si las matrices fueran objetivamente mejores, no tendríamos cadenas.

Piensa en (char *) como string.begin (). La diferencia esencial es que (char *) es un iterador y std :: string es un contenedor. Si te apegas a las cadenas básicas a (char *) te dará lo que std :: string :: iterator hace. Puede usar (char *) cuando desee el beneficio de un iterador y también la compatibilidad con C, pero esa es la excepción y no la regla. Como siempre, tenga cuidado con la invalidación del iterador. Cuando la gente dice (char *) que no es seguro, esto es lo que quieren decir. Es tan seguro como cualquier otro iterador de C ++.

Una de las diferencias es la terminación nula (\ 0).

En C y C ++, char * o char [] tomará un puntero a un carácter único como parámetro y hará un seguimiento a lo largo de la memoria hasta que se scope un valor de memoria 0 (a menudo llamado el terminador nulo).

Las cadenas de C ++ pueden contener caracteres incrustados \ 0, conocer su longitud sin contar.

 #include #include #include using namespace std; void NullTerminatedString(string str){ int NUll_term = 3; str[NUll_term] = '\0'; // specific character is kept as NULL in string cout << str << endl < 

Salida:

 strlen = 11 size = 11 sizeof = 32 Fee s Happy strlen = 11 sizeof = 12 Fee