Pregunta

¿Existe alguna buena razón para utilizar cadenas C en C++ hoy en día?Mi libro de texto los usa en ejemplos en algunos puntos, y realmente siento que sería más fácil usar std::string.

¿Fue útil?

Solución

Las únicas razones por las que he tenido que usarlos es cuando interactúo con bibliotecas de terceros que usan cadenas de estilo C.También puede haber situaciones esotéricas en las que usarías cadenas de estilo C por razones de rendimiento, pero la mayoría de las veces, usar métodos en cadenas de C++ probablemente sea más rápido debido a la incorporación y la especialización, etc.

Puedes usar el c_str() método en muchos casos cuando se trabaja con ese tipo de API, pero debe tener en cuenta que el char * devuelto es constante y no debe modificar la cadena a través de ese puntero.En ese tipo de situaciones, aún puedes usar un vector<char> en su lugar y al menos obtener el beneficio de una administración de memoria más sencilla.

Otros consejos

Un par de notas más sobre el control de la memoria:

Las cadenas C son tipos POD, por lo que se pueden asignar en el segmento de datos de solo lectura de su aplicación.Si declaras y defines std::string constantes en el alcance del espacio de nombres, el compilador generará código adicional que se ejecuta antes main() que llama al std::string constructor para cada constante.Si su aplicación tiene muchas cadenas constantes (p. ej.Si ha generado código C++ que utiliza cadenas constantes), las cadenas C pueden ser preferibles en esta situación.

Algunas implementaciones de std::string admite una función llamada SSO ("optimización de cadenas cortas" u "optimización de cadenas pequeñas") donde std::string La clase contiene almacenamiento para cadenas de hasta una cierta longitud.Esto aumenta el tamaño de std::string pero a menudo reduce significativamente la frecuencia de las asignaciones/desasignaciones de tiendas gratuitas, lo que mejora el rendimiento.Si su implementación de std::string no admite SSO, entonces construir un vacío std::string en la pila seguirá realizando una asignación de tienda gratuita.Si ese es el caso, el uso de cadenas C temporales asignadas a la pila puede resultar útil para el código de rendimiento crítico que utiliza cadenas.Eso sí, debes tener cuidado de no pegarte un tiro en el pie al hacer esto.

¿Porque así es como provienen de numerosas API/bibliotecas?

Digamos que tienes algunas constantes de cadena en tu código, lo cual es una necesidad bastante común.Es mejor definirlos como cadenas C que como objetos C++: más livianos, portátiles, etc.Ahora, si va a pasar estas cadenas a varias funciones, sería bueno que estas funciones aceptaran una cadena C en lugar de requerir un objeto de cadena C++.

Por supuesto, si las cadenas son mutables, entonces es mucho más conveniente usar objetos de cadena C++.

Control de memoria.Recientemente tuve que manejar cadenas (en realidad, blobs de una base de datos) de un tamaño de entre 200 y 300 MB, en una aplicación masiva de subprocesos múltiples.Era una situación en la que una sola copia más de la cadena podría haber superado el espacio de direcciones de 32 bits.Tenía que saber exactamente cuántas copias de la cadena existían.Aunque soy un evangelista de STL, usé char * entonces porque me daba la garantía de que no se asignaría memoria adicional ni copia adicional.Sabía exactamente cuánto espacio necesitaría.

Aparte de eso, el procesamiento de cadenas STL estándar pierde algunas funciones C excelentes para el procesamiento/análisis de cadenas.Afortunadamente, std::string tiene el método c_str() para acceso constante al búfer interno.Sin embargo, para usar printf() aún tienes que usar char * (qué idea tan loca la del equipo de C++ de no incluir una funcionalidad similar a printf, una de las funciones más útiles que JAMÁS haya habido en C.Espero que boost::format se incluya pronto en el STL.

Si una función necesita una constante string Sigo prefiriendo usar 'const char*' (o const wchar_t*) incluso si el programa usa std::string, CString, EString o cualquier otro lugar.

Hay demasiadas fuentes de cadenas en una base de código grande para estar seguro de que la persona que llama tendrá la cadena como std::string y 'const char*' es el mínimo común denominador.

Los libros de texto presentan cadenas C de la vieja escuela porque muchas funciones básicas todavía las esperan como argumentos o las devuelven.Además, proporciona una idea de la estructura subyacente de la cadena en la memoria.

Si el código C++ es "profundo" (cercano al kernel, muy dependiente de las bibliotecas C, etc.), es posible que desee utilizar cadenas C explícitamente para evitar muchas conversiones dentro y fuera de std::string.Además, si está interactuando con otros dominios de lenguaje (Python, Ruby, etc.), puede hacerlo por el mismo motivo.De lo contrario, utilice std::string.

Algunas publicaciones mencionan problemas de memoria.Esa podría ser una buena razón para evitar std::string, pero char* probablemente no sea el mejor reemplazo.Sigue siendo un lenguaje OO.Su propia clase de cadena probablemente sea mejor que un char*.Incluso puede ser más eficiente: puede aplicar la optimización de cadenas pequeñas, por ejemplo.

En mi caso, estaba tratando de obtener aproximadamente 1 GB de cadenas de un archivo de 2 GB, meterlas en registros con aproximadamente 60 campos y luego ordenarlas 7 veces en diferentes campos.El código de mi predecesor tardó 25 horas con char*, mi código se ejecutó en 1 hora.

Después de dedicar mucho, mucho, demasiado tiempo a depurar las reglas de inicialización y todas las implementaciones de cadenas imaginables en varias plataformas, requerimos que las cadenas estáticas sean const char*.

Después de pasar mucho, mucho, demasiado tiempo depurando código char* incorrecto y pérdidas de memoria, sugiero que todas las cadenas no estáticas sean algún tipo de objeto de cadena...hasta que la elaboración de perfiles demuestre que puedes y debes hacer algo mejor ;-)

Dada la opción, generalmente no hay razón para elegir cadenas C primitivas (char*) sobre cadenas C++ (std::string).Sin embargo, a menudo no se puede dar el lujo de elegir.Por ejemplo, std::fstreamLos constructores utilizan cuerdas C, por razones históricas.Además, las bibliotecas C (¡lo has adivinado!) utilizan cadenas C.

En su propio código C++ es mejor usar std::string y extraiga la cadena C del objeto según sea necesario utilizando el c_str() funcion de std::string.

Depende de las bibliotecas que estés usando.Por ejemplo, cuando se trabaja con el MFC, suele ser más fácil usar CString cuando se trabaja con varias partes de la API de Windows.También parece funcionar mejor que std::string en aplicaciones Win32.

Sin embargo, std::string es parte del estándar C++, por lo que si desea una mejor portabilidad, elija std::string.

Para aplicaciones como la mayoría de las plataformas integradas donde no se puede dar el lujo de contar con un montón para almacenar las cadenas que se manipulan y donde se requiere una preasignación determinista de buffers de cadenas.

Las cadenas c no conllevan la sobrecarga de ser una clase.

Las cadenas c generalmente pueden dar como resultado un código más rápido, ya que están más cerca del nivel de la máquina.

Esto no quiere decir que no puedas escribir código incorrecto con ellos.Pueden ser mal utilizados, como cualquier otra construcción.

Existe una gran cantidad de convocatorias de bibliotecas que las exigen por razones históricas.

Aprenda a usar cadenas c y cadenas stl, y úselas cuando tenga sentido hacerlo.

1) "string constante" es una cadena C (const char *), convertirla a const std::string& es un proceso en tiempo de ejecución, no necesariamente simple u optimizado.2) la biblioteca fstream utiliza cadenas de estilo c para pasar nombres de archivos.

Mi regla general es pasar const std::string& si estoy a punto de usar los datos como std::string de todos modos (por ejemplo, cuando los almaceno en un vector), y const char * en otros casos.

Código heredado que no conoce std::string.Además, antes de C++ 11, abrir archivos con std::ifstream o std::ofstream solo era posible con const char* como entrada para el nombre del archivo.

Las cadenas STL son ciertamente mucho más fáciles de usar y no veo ninguna razón para no usarlas.

Si necesita interactuar con una biblioteca que solo toma cadenas de estilo C como argumentos, siempre puede llamar al método c_str() de la clase de cadena.

La razón habitual para hacerlo es que le gusta escribir desbordamientos de búfer en su manejo de cadenas.Las cadenas contadas son tan superiores a las cadenas terminadas que es difícil ver por qué los diseñadores de C alguna vez usaron cadenas terminadas.Fue una mala decisión entonces;Es una mala decisión ahora.

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