2010-11-10 18 views
6

Ha pasado bastante tiempo ahora que he estado codificando en C++ y creo que la mayoría de los que codifican en C++, estarían de acuerdo en que una de las decisiones más delicadas es elegir entre un número casi vertiginoso de tipos de cadenas disponibles. En su mayoría prefiero ATL Cstring por su facilidad de uso y características, pero me gustaría un estudio comparativo de las opciones disponibles. He comprobado SO y no he encontrado ningún contenido que ayude a elegir la cadena correcta. Hay sitios web que indican las conversiones de una cadena a otra, pero eso no es lo que queremos aquí.cadenas de C++, ¿cuándo usar qué?

Me encantaría tener una comparación basada en la especialidad, el rendimiento, la portabilidad (Windows, Mac, Linux/Unix, etc.), facilidad de uso/características, soporte de múltiples idiomas (Unicode/MBCS), contras (en su caso), y cualquier otro caso especial.

Estoy enumerando las cadenas que he encontrado hasta ahora. Creo que habría más, por lo que podemos editar esto más tarde para adaptar otras opciones. Eso sí, he trabajado sobre todo en Windows, por lo que la lista refleja la misma:

  1. char*
  2. std::string
  3. de STL basic_string
  4. de ATL CString
  5. de MFC CString
  6. BSTR
  7. _bstr_t
  8. CComBstr
+0

Úselos a todos. Terminará con todos ellos allí de todos modos, así que no se moleste en intentar ser quisquilloso al comienzo –

+1

Use 'CComBstr' solo cuando trabaje con COM. –

+0

Puede agregar cadenas ICU en la mezcla para un manejo Unicode adecuado. –

Respuesta

7

no me refiero a poner un amortiguador en su entusiasmo por este, pero siendo realistas, que es ineficaz para mezclar una gran cantidad de tipos de cadenas en el proyecto, por lo que cuanto mayor sea el proyecto tiene la más inevitable que debería conformarse con std :: string (que es un typedef para una instanciación de la cadena básica de STL para tipo char, no una entidad diferente), dado que es la única opción de valor semántico estándar. char * está bien principalmente para cadenas de tamaño fijo (por ejemplo, literales de cadena, almacenamientos intermedios de tamaño fijo) o en la interfaz con C.

¿Por qué digo que es ineficiente? Usted termina con instancias innecesarias de plantillas para la variedad de argumentos de cadenas (permutaciones incluso para argumentos múltiples). Se encuentra llamando a funciones que desean cargar un resultado en una cadena &, luego tiene que llamar a .c_str() y construir otro tipo, asignando memoria redundante. Incluso const std :: string & requiere una cadena temporal si se llama utilizando un ASCIIZ char * (por ejemplo, a algún otro buffer de tipo de cadena). Cuando desea escribir una función para manejar el tipo de cadena que una persona que llama quiere usar, se le empuja hacia plantillas y, por lo tanto, código en línea, tiempos de compilación más largos y compilaciones de recompilación (hay algunas formas de mitigar esto, pero se vuelven complejas y para ser prácticos o automatizados, tienden a requerir cambios en los diversos tipos de cadenas, por ejemplooperador de casting o función de miembro que devuelve algún objeto común de interfaz/proxy).

Es posible que los proyectos necesiten utilizar tipos de cadena no estándar para interactuar con las bibliotecas que desean usar, pero desea minimizar eso y limitar la penetración si es posible.

+0

Para obtener más información sobre 'std :: string' y unicode, mira [aquí] (http://stackoverflow.com/questions/402283/stdwstring-vs-stdstring). –

2

La triste historia de C++ manejo de cadenas es demasiado deprimente para mí escribir un ensayo sobre, pero sólo un par de puntos:

  • ATL y MFC CString son la misma cosa (mismo código y todo). Se fusionaron hace años.

  • Si está utilizando _bstr_t o CComBstr, probablemente no use BSTR excepto en las llamadas a las API de otras personas que toman BSTR.

+0

@ Will - Gracias. Eso ayuda. –

1

Obviamente, solo los primeros tres son portátiles, por lo que deberían preferirse en la mayoría de los casos. Si está haciendo C++, entonces debe evitar char * en la mayoría de los casos, ya que los punteros sin procesar y las matrices son propensas a errores. La interconexión con C de bajo nivel, como las llamadas al sistema o los controladores, es la excepción. std:string debe ser preferido por defecto, en mi humilde opinión, porque se adapta tan bien con el resto de la STL.

Nuevamente, en mi humilde opinión, si necesita trabajar con, por ejemplo, MFC, debe trabajar con todo como std::string en su lógica comercial, y traducir ay desde CString cuando acierta con las funciones de WinApi.

+1

Supongo que quería escribir * should not 'char *' *? –

+0

@Space: ¡Gracias! –

2
  • char* - rápido, características incluyen aquellos que están en < cstring> cabecera, propenso a errores (demasiado bajo nivel)

  • std::string - esto es en realidad un typedef para std::basic_string<char, char_traits<char> > Una cosa hermosa - primer de todo, es rápido también. En segundo lugar, puede usar todos los algoritmos <> s porque basic_string proporciona iteradores. Para el soporte de caracteres anchos hay otro typedef, wstring que es, std::basic_string<wchar_t, char_traits<wchar_t> >. Esto (basic_string) es un tipo estándar, por lo tanto, es absolutamente portátil. Yo iría con este.

  • Las CStrings de ATL y MFC ni siquiera proporcionan iteradores, por lo tanto, son una abominación para mí, porque son un envoltorio de clase alrededor de las cadenas de tipo c y están mal diseñadas. IMHO

  • no sé el resto.

Esperamos que esta información parcial ayuda a

+0

Gracias. Eso realmente ayuda. –

1

2 y 3 son los mismos. 4 y 5 son lo mismo, también. 7 y 8 son envoltorios de 6. Así que, posiblemente, la lista contiene solo cadenas de C, cadenas estándar de C++, cadenas de C++ de Microsoft y cadenas COM de Microsoft. Eso le da la respuesta: en C++ estándar, use las cadenas estándar de C++ (std::string)

Cuestiones relacionadas