Pregunta

¿Cuándo debo usar? std::string y cuando debo usar char* para gestionar matrices de char¿Está en C++?

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

¿Hay otros escenarios a considerar?

¿Fue útil?

Solución

Puede pasar cadenas std :: por referencia si son grandes para evitar la copia, o un puntero a la instancia, por lo que no veo ninguna ventaja real usando punteros de caracteres.

Utilizo std :: string / wstring para más o menos todo lo que es texto real. Sin embargo, 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 hay excepciones a todo esto.

Otros consejos

Mi punto de vista es:

  • Nunca use char * si no llama a " C " código.
  • Utilice siempre std :: string: es más fácil, es más amigable, está optimizado, es estándar, evitará que tenga errores, se ha verificado y comprobado que funciona.

Uso de cadena sin formato

Sí, a veces realmente puedes hacer esto. Al usar const char *, matrices de caracteres asignadas en la pila y literales de cadena, puede hacerlo de tal manera que no haya asignación de memoria en absoluto.

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 alguna garantía sobre la longitud de la cadena que se está copiando, o verifique y maneje las 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 insegura.

Cómo las plantillas pueden ayudar a escribir buffers de caracteres seguros

En cuanto a la seguridad de los buffers char [], las plantillas pueden ayudar, ya que pueden crear una encapsulación para manejar el tamaño del buffer por usted. Se implementan plantillas como esta, p. 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 <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;
}

Una ocasión que DEBES usar char* y no std::string es cuando necesitas constantes de cadena estáticas.La razón de esto es que no tiene ningún control sobre el orden en que los módulos inicializan sus variables estáticas, y otro objeto global de un módulo diferente puede hacer referencia a su cadena antes de que se inicialice. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables

std::string ventajas:

  • administra la memoria por usted (la cadena puede crecer y la implementación le asignará un búfer más grande)
  • La interfaz de programación de nivel superior funciona bien con el resto de STL.

std::string contras:- Dos instancias de cadena STL distintas no pueden compartir el mismo búfer subyacente.Entonces, si pasas por valor, siempre obtendrás una copia nueva.- Hay alguna penalización en el rendimiento, pero yo diría que, a menos que sus requisitos sean especiales, es insignificante.

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

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

En realidad, en C ++, <=> a menudo se usan para palabras pequeñas fijas, como opciones, nombre de archivo, etc.

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

  • las cadenas, en general, son más seguras que char *, normalmente cuando está haciendo cosas con char * debe verificar las cosas para asegurarse de que las cosas estén bien, en la clase de cadena todo esto se hace por usted.
  • Por lo general, cuando use char *, tendrá que liberar la memoria que asignó, no tiene que hacerlo con una cadena, ya que liberará su búfer interno cuando se destruya.
  • Las cadenas funcionan bien con c ++ stringstream, IO formateado es muy fácil.

Cuándo usar char *

  • Usar char * te da más control sobre lo que está sucediendo " detrás de " las escenas, lo que significa que puede ajustar el rendimiento si lo necesita.

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

Si quiere usar bibliotecas C, tendrá que lidiar con cadenas C. Lo mismo se aplica si desea 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 en 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. Por lo tanto, cualquier algoritmo que diseñe sobre los iteradores es esencialmente idéntico al mismo algoritmo sobre char * en términos de rendimiento.

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

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

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

si está utilizando la matriz de caracteres en texto similar, etc. use std :: string más flexible y más 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, es mejor usar 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 [] conduce a una sobrecarga, pero siempre puede extraer la dirección del búfer e indexarla exactamente como si fuera un char *.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top