Sé un poco de C y ahora estoy echando un vistazo a C ++. Estoy acostumbrado a las matrices de caracteres para tratar con cadenas C, pero mientras miro el código C ++ veo que hay ejemplos que utilizan tanto el tipo de cadena como las matrices de caracteres:
#include <iostream>
#include <string>
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 <iostream>
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 (¿obvia?), Pero sería bueno si alguien pudiera decirme cuál es exactamente la diferencia entre esas dos formas de manejar cadenas en C ++ (rendimiento, integración API, la forma en que cada una es mejor, ...).
Gracias.
Respuestas:
Una matriz de caracteres es solo eso: una matriz de caracteres:
Una cadena es una clase que contiene una matriz de caracteres, pero la administra automáticamente por usted. 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 de caracteres de una cadena de esta manera:
Las cadenas de C ++ pueden contener caracteres \ 0 incrustados, conocer su longitud sin contar, son más rápidas que las matrices de caracteres asignadas en el montón para textos cortos y lo protegen de 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 su uso a través de los límites de DLL, ya que esto requeriría que cualquier usuario de dicha función de DLL se asegure de que está usando exactamente el mismo compilador y la implementación de tiempo de ejecución de C ++, para no arriesgarse a que su clase de cadena se comporte de manera diferente.
Normalmente, una clase de cadena también liberaría su memoria de almacenamiento dinámico en el almacenamiento dinámico de llamadas, por lo que solo podrá liberar memoria nuevamente 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 cadenas C en sus funciones públicas (dll / so-expuestos).
fuente
Arkaitz es correcto que
string
es un tipo administrado. Lo que esto significa para usted es que nunca debe preocuparse por la longitud de la cadena ni preocuparse por liberar o reasignar la memoria de la cadena.Por otro lado, la
char[]
notación en el caso anterior ha restringido el búfer de caracteres a exactamente 256 caracteres. Si trató de escribir más de 256 caracteres en ese búfer, en el mejor de los casos sobrescribirá otra memoria que "posee" su programa. En el peor de los casos, intentará sobrescribir la memoria que no posee y su sistema operativo matará su programa en el acto.¿Línea de fondo? Las cadenas son mucho más amigables para los programadores, los char [] s son mucho más eficientes para la computadora.
fuente
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 usted.
En términos de API y biblioteca estándar, todo se implementa en términos de cadenas y no char [], pero todavía hay muchas funciones de la biblioteca que reciben char [], por lo que es posible que deba usarlo para ellos, aparte de eso, lo haría siempre use std :: string.
En términos de eficiencia, por supuesto, un búfer sin procesar 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 necesita comparar personaje por personaje.
fuente
Personalmente, no veo ninguna razón por la que a uno le gustaría usar char * o char [], excepto por la compatibilidad con el código anterior. std :: string no es más lento que usar una c-string, 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 todos los sentidos de la palabra es exactamente lo mismo que usar un indexador de cadena c). El uso del método at también proporciona seguridad comprobada en los límites, algo que no se obtiene con las cadenas en C, a menos que lo escriba. Su compilador a menudo optimizará el uso del indexador en modo de lanzamiento. Es fácil perder el tiempo con cuerdas en C; cosas como eliminar vs eliminar [], seguridad de excepción, incluso cómo reasignar una cadena en C.
Y cuando tenga que lidiar con conceptos avanzados como tener cadenas COW y no COW para MT, etc., necesitará std :: string.
Si está preocupado por las copias, siempre y cuando use referencias y referencias constantes siempre que pueda, no tendrá gastos generales debido a las copias, y es lo mismo que haría con la cadena c.
fuente
Las cadenas tienen funciones auxiliares y administran matrices de caracteres automáticamente. Puede concatenar cadenas, para una matriz de caracteres necesitaría copiarla en una nueva matriz, las cadenas pueden cambiar su longitud en tiempo de ejecución. Una matriz de caracteres 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, se hicieron para que no tenga que usar matrices. Si las matrices fueran objetivamente mejores, no tendríamos cadenas.
fuente
Piense en (char *) como string.begin (). La diferencia esencial es que (char *) es un iterador y std :: string es un contenedor. Si se apega a las cadenas básicas, a (char *) le dará lo que hace std :: string :: iterator. 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 *) no es seguro, esto es lo que quieren decir. Es tan seguro como cualquier otro iterador de C ++.
fuente
Una de las diferencias es la terminación nula (\ 0).
En C y C ++, char * o char [] tomará un puntero a un único char como parámetro y rastreará a lo largo de la memoria hasta que se alcance un valor de memoria 0 (a menudo llamado terminador nulo).
Las cadenas de C ++ pueden contener caracteres \ 0 incrustados, conozca su longitud sin contar.
Salida:
fuente