¿Cuándo debo usar std::string
y cuándo debo usar char*
para administrar matrices de char
s en C ++?
Parece que debería usarlo char*
si el rendimiento (velocidad) es crucial y está dispuesto a aceptar un negocio arriesgado debido a la gestión de la memoria.
¿Hay otros escenarios a considerar?
char *
casi no tiene gastos generales.std::string
No sé exactamente qué gastos generales tiene, es probable que dependa de la implementación. Difícilmente espero que la sobrecarga sea mucho mayor que la de un puntero de char. Dado que no poseo una copia del estándar, no puedo detallar ninguna garantía hecha por el estándar. Es probable que cualquier diferencia de rendimiento varíe según las operaciones a realizar.std::string::size
podría almacenar el tamaño junto a los datos del carácter y, por lo tanto, ser más rápido questrlen
.append(const string&)
y enappend(const char*, size_t)
lugar deoperator+=()
.Mi punto de vista es:
fuente
Uso de cadenas sin procesar
Sí, a veces realmente puedes hacer esto. Al usar const char *, las matrices de char asignadas en la pila y los literales de cadena, puede hacerlo de tal manera que no haya ninguna asignación de memoria.
Escribir dicho código requiere a menudo más pensamiento y cuidado que usar cadenas o vectores, pero con las técnicas adecuadas se puede hacer. Con las técnicas adecuadas, el código puede ser seguro, pero siempre debe asegurarse de que, al copiar en char [], tenga algunas garantías sobre la longitud de la cadena que se está copiando, o verifique y maneje cadenas de gran tamaño con elegancia. No hacerlo es lo que le dio a la familia de funciones strcpy la reputación de ser insegura.
Cómo las plantillas pueden ayudar a escribir búferes de caracteres seguros
En cuanto a la seguridad de los búferes char [], las plantillas pueden ayudar, ya que pueden crear una encapsulación para manejar el tamaño del búfer por usted. Microsoft implementa, por ejemplo, plantillas como ésta para proporcionar reemplazos seguros para strcpy. El ejemplo aquí se extrae de mi propio código, el código real tiene muchos más métodos, pero esto debería ser suficiente para transmitir la idea básica:
template <int Size> class BString { char _data[Size]; public: BString() { _data[0]=0; // note: last character will always stay zero // if not, overflow occurred // all constructors should contain last element initialization // so that it can be verified during destruction _data[Size-1]=0; } const BString &operator = (const char *src) { strncpy(_data,src,Size-1); return *this; } operator const char *() const {return _data;} }; //! overloads that make conversion of C code easier template <int Size> inline const BString<Size> & strcpy(BString<Size> &dst, const char *src) { return dst = src; }
fuente
char*
las cadenas no siempre están en la pila.char *str = (char*)malloc(1024); str[1024] = 0;
Una ocasión que DEBE usar
char*
y nostd::string
es cuando necesita constantes de cadena estáticas. La razón de esto es que no tiene ningún control sobre los módulos de orden que inicializan sus variables estáticas, y otro objeto global de un módulo diferente puede referirse a su cadena antes de que se inicialice. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variablesstd::string
pros:std::string
contras: - dos instancias de cadenas STL distintas no pueden compartir el mismo búfer subyacente. Entonces, si pasa por valor, siempre obtendrá una nueva copia. - Hay una penalización de rendimiento, pero yo diría que, a menos que sus requisitos sean especiales, es insignificante.fuente
Debe considerar su uso
char*
en los siguientes casos:En realidad, en C ++, a
char*
menudo se usan para palabras pequeñas fijas, como opciones, nombre de archivo, etc.fuente
Cuándo usar un std :: string de c ++:
Cuando usar char *
fuente
Utilice (const) char * como parámetros si está escribiendo una biblioteca. Las implementaciones de std :: string difieren entre diferentes compiladores.
fuente
Si desea utilizar bibliotecas C, tendrá que lidiar con cadenas C. Lo mismo se aplica si desea exponer su API a C.
fuente
Puede esperar que la mayoría de las operaciones en un std :: string (como por ejemplo
find
) estén lo más optimizadas posible, por lo que es probable que funcionen al menos tan bien como una contraparte de C pura.También vale la pena señalar que los iteradores std :: string a menudo se asignan a punteros en la matriz de caracteres subyacente. Entonces, cualquier algoritmo que diseñe sobre iteradores es esencialmente idéntico al mismo algoritmo sobre char * en términos de rendimiento.
Las cosas a tener en cuenta son, por ejemplo
operator[]
, que la mayoría de las implementaciones de STL no realizan la verificación de límites y deberían traducir esto a la misma operación en la matriz de caracteres subyacente. AFAIK STLPort opcionalmente puede realizar la verificación de límites, momento en el que este operador sería un poco más lento.Entonces, ¿qué te aporta el uso de std :: string? Le absuelve de la gestión manual de la memoria; cambiar el tamaño de la matriz se vuelve más fácil y, por lo general, debe pensar menos en liberar memoria.
Si le preocupa el rendimiento al cambiar el tamaño de una cadena, hay una
reserve
función que puede resultarle útil.fuente
si está utilizando la matriz de caracteres en texto similar, etc., use std :: string más flexible y fácil de usar. ¿Si lo usa para algo más como el almacenamiento de datos? use matrices (prefiera vectores)
fuente
Incluso cuando el rendimiento es crucial, es mejor usarlo
vector<char>
: permite la asignación de memoria por adelantado (método reserve ()) y lo ayudará a evitar pérdidas de memoria. El uso de vector :: operator [] genera una sobrecarga, pero siempre puede extraer la dirección del búfer e indexarlo exactamente como si fuera un char *.fuente
AFAIK internamente, la mayoría de std :: string implementan copia en escritura, semántica contada de referencia para evitar gastos generales, incluso si las cadenas no se pasan por referencia.
fuente