char * vs std :: string en c ++

¿Cuándo debería usar std::string y cuándo debo usar char* para administrar matrices de caracteres en C ++?

Parece que debes usar char* si el rendimiento (velocidad) es crucial y estás dispuesto a aceptar algunos negocios arriesgados debido a la administración de la memoria.

¿Hay otros escenarios para considerar?

Puede pasar std :: strings por referencia si son grandes para evitar copiar, o un puntero a la instancia, por lo que no veo ninguna ventaja real con los punteros de char.

Uso std :: string / wstring para más o menos todo lo que es texto real. char * es útil para otros tipos de datos y puede estar seguro de que se desasigna como debería. De lo contrario std :: vector es el camino a seguir.

Probablemente haya excepciones a todo esto.

Mi punto de vista es:

  • Nunca use char * si no llama al código “C”.
  • Siempre use std :: string: es más fácil, es más amigable, está optimizado, es estándar, evitará que tenga errores, se verificó y se demostró que funciona.

Uso de cadena sin procesar

Sí, a veces realmente puedes hacer esto. Al usar const char *, los arreglos de caracteres asignados en la stack 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 si controla y manipula cadenas de gran tamaño con gracia. No hacerlo es lo que le dio a la familia de funciones Strcpy la reputación de ser inseguro.

Cómo las plantillas pueden ayudar a escribir memorias tampón de carbón seguro

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. Plantillas como esta son implementadas, por ejemplo, por Microsoft 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  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  inline const BString & strcpy(BString &dst, const char *src) { return dst = src; } 

Debería considerar usar char* en los siguientes casos:

  • Esta matriz se pasará en el parámetro.
  • Usted sabe de antemano el tamaño máximo de su matriz (lo sabe O lo impone).
  • No harás ninguna transformación en esta matriz.

En realidad, en C ++, char* se usa a menudo para palabras pequeñas y fijas, como opciones, nombre de archivo, etc.

Una ocasión en la que DEBE usar char* y no std::string es cuando necesita constantes de cadenas estáticas. La razón de esto es que no tiene ningún control sobre los módulos de orden inicializar 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_Variables

std::string pros:

  • administra la memoria por usted (la cadena puede crecer, y la implementación le asignará un buffer más grande)
  • Interfaz de progtwigción de nivel superior, funciona muy bien con el rest de STL.

std::string cons: – dos instancias de cadenas STL distintas no pueden compartir el mismo buffer subyacente. Entonces, si pasa por valor, siempre obtiene una copia nueva. – hay alguna penalización de rendimiento, pero yo diría que a menos que sus requisitos sean especiales, es insignificante.

Cuándo usar c ++ std :: string:

  • las cadenas, en general, son más seguras que char *, normalmente cuando estás haciendo cosas con char * tienes que verificar las cosas para asegurarte de que todo va bien, en la clase de cadenas todo esto se hace por ti.
  • Por lo general, al usar char *, tendrá que liberar la memoria que asignó, no tiene que hacer eso con una cadena, ya que liberará su búfer interno cuando se destruya.
  • Las cadenas funcionan bien con cadenas de caracteres c ++, IO formateado es muy fácil.

Cuándo usar char *

  • Usar char * le da más control sobre lo que está sucediendo “detrás” de las escenas, lo que significa que puede ajustar el rendimiento si es necesario.

Use (const) char * como parámetros si está escribiendo una biblioteca. Las implementaciones de std :: string difieren entre los diferentes comstackdores.

Si desea usar bibliotecas C, tendrá que lidiar con C-strings. Lo mismo aplica si quiere exponer su API a C.

Puede esperar que la mayoría de las operaciones en una cadena std :: (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 C pura.

También vale la pena señalar que los iteradores std :: string con frecuencia se asignan a punteros en la matriz char subyacente. Por lo tanto, cualquier algoritmo que diseñe sobre los iteradores es esencialmente idéntico al mismo algoritmo además de char * en términos de rendimiento.

Las cosas a tener en cuenta son, por ejemplo, el operator[] : la mayoría de las implementaciones de STL no realizan la comprobación de límites, y deben traducir esto a la misma operación en la matriz de caracteres subyacente. AFAIK STLPort puede realizar opcionalmente la comprobación de límites, en cuyo punto este operador sería un poco más lento.

Entonces, ¿qué te sirve usar std :: string? Le absuelve de la gestión de memoria manual; cambiar el tamaño de la matriz se vuelve más fácil, y generalmente tiene que pensar menos en liberar la memoria.

Si le preocupa el rendimiento al cambiar el tamaño de una cuerda, hay una función de reserve que puede serle útil.

si está usando la matriz de caracteres en texto similar, use std :: string de manera más flexible y fácil de usar. Si lo usa para otra cosa como el almacenamiento de datos? usar matrices (preferir vectores)

Incluso cuando el rendimiento es crucial, mejor utilice vector : permite la asignación de memoria por adelantado (método de reserva) y lo ayudará a evitar memory leaks. El uso de vector :: operator [] conduce a una sobrecarga, pero siempre puede extraer la dirección del búfer e indexarlo exactamente como si fuera un char *.

AFAIK internamente std :: string implementa copia en escritura, semántica contada de referencia para evitar gastos generales, incluso si las cadenas no se pasan por referencia.