2010-10-26 9 views
20

¿Está mal el uso de C en C++?Usando/mezclando C en código C++?

Muchas personas me han dicho que usar C en C++ es malo porque no es tan seguro y requiere más administración de la memoria. Sigo diciéndoles que, mientras sepas lo que estás haciendo, y borres tus "nuevos" y liberes tus "malloc", entonces C no es un problema.

Actualmente estoy en un foro donde se lleva a cabo un argumento sobre std::string contra char*. Algunas personas dicen que asignar un simple bloque de memoria char* es más eficiente, y siempre que lo desasigna, está bien. Por otro lado, tenemos gente que dice que std::string es superior porque no tiene administración de memoria pero es menos eficiente.

Así que la cuestión principal es:

  • es la mezcla de C/C++ malo? ¿SOLAMENTE deberías usar 100% C++ cuando estás codificando C++?

¡Cualquier respuesta sería apreciada!

+0

C++ es un superconjunto de C. Por lo tanto, cualquier programa C válido es un programa válido de C++, y no hay tal cosa como "mezclar" C en C++. – Jonathan

+0

Imagino que está hablando de las características c que han quedado obsoletas en C++, como malloc –

+27

@Jonathan: 'int main() {int class = 2; } '(C válido, C++ no válido) C++ no es un superconjunto de C; C y C++ comparten un subconjunto común. –

Respuesta

15

Sigo diciéndoles que mientras sepas lo que estás haciendo, y borres los tuyos y liberes tu malloc, entonces C no es un problema.

Esto es cierto; si eres extraordinariamente cuidadoso y te aseguras de limpiar manualmente las cosas, entonces no es un problema. ¿Pero realmente tienes tiempo para hacer eso? Cada llamada al new puede arrojar std::bad_alloc. ¿Tiene siempre captura cada excepción que se puede lanzar y limpiar manualmente cualquier recurso?

Me arriesgaría a adivinar la respuesta a eso es "no", porque es muy tedioso escribir un código como ese y es difícil estar absolutamente seguro de que el código escrito así es correcto, incluso en el caso de fallas raras.

Si la respuesta es "sí", ¿por qué pierdes tanto tiempo preocupándote por la gestión de recursos? Las expresiones idiomáticas de C++, como la gestión de recursos vinculada al alcance (SBRM, más conocida como adquisición de recursos es la inicialización (RAII)) y las bibliotecas, como la biblioteca de plantillas estándar, están ahí para ayudarlo a escribir el código correcto más fácilmente. ¿Por qué hacer las cosas de la manera difícil cuando no es necesario?

¿SÓLO debe utilizar 100% C++ cuando su código C++?

Sí, aunque si hay una biblioteca C que hace algo que necesita, o si tiene un código C heredado que desea utilizar, puede usar ese código; solo asegúrate de tener cuidado. A menudo, la forma más limpia de interoperar con el código C es escribir un contenedor C++ a su alrededor.

+2

No veo nada en su respuesta específica a 'C en un proyecto de C++'. sus argumentos parecen estar en contra de C en general, y por lo tanto caen en la tierra de 'escoge tu veneno'. – Javier

+1

@Javier: No, mi respuesta es específicamente sobre el uso de C en el código de C++. No hay excepciones en C, por lo que siempre sabrá cuándo puede regresar una función y siempre sabrá cuándo debe limpiar los recursos (salvo el uso loco de 'longjmp' o algo así). Lleva un poco de trabajo administrar manualmente los recursos en C; es casi imposible en C++. –

+2

oh, a la derecha. las excepciones son una razón importante para no llamar a C++ desde C. pero llamar a C desde C++ está bien (y mucho más) – Javier

11

Mi fuerte creencia es que su pregunta no tiene que ver con C o C++ en absoluto. Su pregunta es sobre el intercambio de eficacia dudosa por seguridad. Sí, C puede ser más eficiente. Pero, ¿cuánto más eficiente? ¿Y qué pagas por eso? Estas son las preguntas que debes responder. En la mayoría de los casos, la sobrecarga de cadena vs. const char * no se nota. Si está desarrollando una aplicación de eficiencia extremadamente crítica, ¿por qué no codificarla en C en primer lugar?

+1

estrictamente hablando, con C++ se agregan campanas y silbatos (y estos no necesariamente reducen el rendimiento) - pero hay Son momentos en los que tiene que sacrificar estándares para el rendimiento en bruto (sprintf vs. iostreams, atoi (& friends) vs lexical_cast, etc.) – Nim

+0

@Nim: Hay momentos en los que tales tiempos son extremadamente raros. Y comprende una parte muy pequeña de todo nuestro código. Si toda la aplicación es tan crítica en cuanto al tiempo, ¿por qué no usar assembly o C? Ese es mi punto –

+0

Hay muchas razones personales para agradar C sobre C++, el rendimiento es muy pequeño. al hacer C++, prefiero hacerlo completamente en C++; pero realmente entiendo disgusto por muchas cosas. por cierto, std :: string es uno de mis favoritos, dame un char * en cualquier momento. – Javier

2

regrabando el argumento sobre std :: string vs char *.

std :: string no va a ser más lento que char * (para heap char *); muchas implementaciones son mucho más rápidas porque usan grupo de memoria privada. Y de todos modos, la robustez de std :: string supera con creces cualquier improbable (improbable) golpe

+0

E incluso si la implementación * no es * más rápida que el uso de cadenas estilo C, la utilidad de la clase 'string' compensa cualquier pérdida de rendimiento IMO. No intercambie la facilidad de mantenimiento y la legibilidad por el rendimiento * a menos que * no esté cumpliendo con los requisitos de un rendimiento sólido ** y ** ya haya realizado todas las optimizaciones de alto nivel que pueda. –

1

La respuesta simple aquí es perfil; determine cuál funciona mejor en su estuche y úselo prudentemente!

2

La respuesta es, por supuesto: depende.

Generalmente, debe evitar mezclar cosas que pueden causar confusión, que pueden conducir a errores difíciles de encontrar. Solo porque "usted sabe lo que hace" no significa que la próxima persona que toque su código sabrá lo que estaba haciendo. Si está desarrollando un código que solo usará alguna vez, entonces es , probablemente está bien, pero rara vez es así.

Usar C para el rendimiento está bien si se tiene cuidado. Pero solo debes hacerlo si SABES que necesitas el rendimiento. La optimización prematura de bajo nivel es obra del diablo.

Es un caso muy raro donde el uso de char * over std :: string le brindará notables beneficios de rendimiento, y solo vale la pena la molestia de la administración de la memoria en los casos en que sí lo haga.

7

Estoy realmente sorprendido por la polarización en las respuestas y los comentarios al respecto.

En mis ojos, la respuesta es bastante simple:

Al escribir un proyecto de C++, utilice C++, C evitar (y familiar) y se adhieren a la biblioteca estándar y STL. Asegure una interfaz C++ homogénea (¡es un proyecto C++ después de todo!) Al usar un proyecto externo en C, que está escrito en C, por supuesto puede usarlo. (Ver ejemplos a continuación)

Dos ejemplos típicos:

  1. Escribe una programa en C++/biblioteca que hace cálculos científicos. Definitivamente usaría GSL (Biblioteca Científica GNU), y está escrito en C. Solo hay algunas advertencias (como inicialización especializada y funciones gratuitas para estructuras y funciones específicas dentro de GSL), que pueden ser absorbidas en un typedef std::unique_ptr. También está la cuestión del manejo de errores: si es necesario/deseado, se pueden abstraer los códigos de error de comprobación en un mecanismo de excepción, o puede conservar los códigos de error incluidos en las funciones de cálculo. GSL tiene una forma de configurar un manejador de errores, imagino que otras bibliotecas C tienen esa funcionalidad.

  2. Escribiendo un programa en C++ utilizando la API de Win32, que está terriblemente basada en C. Estoy hablando del uso ligero de la API, como leer los archivos en un directorio, verificar si existe un archivo, etc., no un GDI + pesado u otras cosas. Me gusta envolver todas las funciones C que la API de Win32 expone en agradables funciones de estilo C++, quizás con las excepciones necesarias y devolver un std::string en lugar de tener que pasar un buffer char* como argumento.

Entiendo que ambos ejemplos son bastante ... superficiales ... pero creo que expresan una idea lo suficientemente general.

1

¿Está utilizando C en C++ mal?

Aunque una pregunta subjetiva: en mi opinión, tome medidas importantes para evitar el uso de c en los programas de C++.

Muchas personas me han dicho que usar C en C++ es malo porque no es tan seguro y requiere más administración de la memoria. Sigo diciéndoles que mientras sepas lo que estás haciendo, y borres los nuevos y liberes los malloc, entonces C no es un problema.

estás reintroduciendo las deficiencias y peligros que C++ fue diseñado para superar, y no es la forma en que se hacen las cosas en los programas de C++.

comprobo/rechazo/reescribo rutinariamente el código que ingresa a las bases de código que es "c con características de C++", o "C++ con características c". incluso llego a cambiar malloc, libre, etc. para afirmar en espacios de nombres raíz (entre otras cosas).

Actualmente estoy en un foro donde se lleva a cabo una discusión sobre std :: string vs. a char *. Algunas personas dicen que asignar un simple bloque de memoria char * es más eficiente, y siempre que lo desasigna, está bien. Por otro lado, tenemos personas que dicen que std :: string es superior porque no tiene administración de memoria pero es menos eficiente.

hay más opciones para representar una cadena en C++ que std :: cadena.

En mi opinión, es completamente válido crear una nueva clase que represente una cadena y que tenga un propósito particular, o que siga contratos adicionales (cuando sea necesario). parte de los contratos de tales representaciones de cadenas son (por supuesto) que administran sus propios recursos usando new[]/delete[] cuando se utiliza memoria dinámica.

si la eficiencia es tan importante y std::string es menos que ideal para una tarea específica, entonces C++ es lo suficientemente potente como para expresar su intención para estos casos específicos mediante la creación de una interfaz especializada en C++. hay muchos casos en que esto es aceptable (imo), pero no siempre vale la pena el tiempo invertido. en cualquier caso, es más fácil de administrar que la integración de c modismos/estilos/peligros en los programas de C++.

Así que la pregunta principal aquí es: ¿está mal la mezcla de C/C++? ¿Debería usar SÓLO 100% C++ cuando su código C++?

es mejor crear soluciones basadas en objetos reutilizables para sus necesidades. los peligros en el ejemplo proporcionado pueden encapsularse por completo (si esta optimización realmente vale la pena el tiempo de inversión), y escribirse para usar modismos C++, sin pérdida de rendimiento y con mejor capacidad de mantenimiento.

1

En el caso específico de string frente const char *, se debe utilizar al descubierto const char * para todas las variables que mantienen las constantes de cadena (y sólo constantes de cadena), la conversión a string sólo cuando pasa a una API que requiere string. Hacer esto consistentemente puede eliminar enormes cantidades de constructores globales, no causa dolores de cabeza en la asignación de memoria (ya que las constantes de cadena son permanentes, datos constantes) y la OMI realmente aclara el código: verá const char *, usted sabe que va a ser una cadena constante.

1

Si estás hablando de técnicas, tendré cuidado de decir que hacer lo anterior está bien.

Escribir programas en C++ utilizando técnicas de organización de programas estilo C probablemente dará como resultado muchos problemas de mantenimiento. En general, el programador ignora muchos de los beneficios que proporciona un lenguaje orientado a objetos. Simplemente porque mucha de la sintaxis de C es válida, C++ y la transferencia de muchas técnicas de codificación no significa que deba hacerlas en C++.

Dicho esto, usar las funciones C y las cosas no es un problema, siempre y cuando tengas cuidado con su uso. En algunos casos, debes hacerlo.

3

La mejor pregunta aquí es, ¿por qué usar C? ¿El desempeño? En primer lugar, creo que no existe una diferencia de rendimiento mensurable para un programa con la misma función. En segundo lugar, tendrías que perfilar y probar que para tu caso específico, C++ es más lento. En tercer lugar, está renunciando a una gran cantidad de seguridad de aplicaciones mediante el uso de C en lugar de C++.

+2

Depende de cómo lo haga. Nunca busqué en el código fuente, pero encontré que para un uso particular, Boost.Regex, que se desarrolla en C++, es aproximadamente 100 veces más lento que PCRE para la correspondencia de expresiones regulares en cadenas largas. Presumiblemente, este es un problema de rendimiento de alto nivel en el diseño, pero probablemente sea así por la forma en que se adhiere a las expresiones idiomáticas de C++ generalmente "aceptadas". Simplemente TIENE que operar en C-strings sin procesar para obtener un rendimiento óptimo. – Gerald

+0

@Gerald: Eso es algo muy diferente. En primer lugar, realmente midió y determinó que boost :: regex es más lento que PCRE. Supongo que luego determinó que se trataba de un problema real de rendimiento en su aplicación. Luego fuiste y usaste PCRE. Y si boost :: regex fue tu propio código, solo fuiste y usaste PCRE si determinabas que boost :: regex no podía ser reparado o optimizado. – Puppy

+0

.. cierto. Solo estaba siendo un poco pedante con respecto a su afirmación de que "creo que no hay una diferencia de rendimiento mensurable para un programa con la misma función". No puede ser, dependiendo de cuánto te apegas a "C++ - ness", o algo así;) – Gerald

2

Sí que es malo para mezclar C y C++, cualquier razón no tiene nada que ver con el rendimiento o la seguridad:

Es mala causa de un mantenimiento:
* programador de C++ espera que todo el código se comporte como C++ .
* un programador en C espera que todo el código se comporte como C.

Así que cuando mezclas C++ y C, rompes las expectativas de ambos programadores sobre cómo deberían funcionar las cosas.

0

Bueno, estoy en una situación extraña. Estoy trabajando en un sistema que se supone que está en C++ (se usa el compilador C++ y se usa el término C++), pero todo está escrito en C. Esto es muy frustrante, porque está llegando a un punto en el que tengo que 'probar' 'C++ es mejor usar que C, aunque estamos codificando en C++. Fue todo un infierno cuando presenté std :: string. Mi opinión es que ahora todo está empezando a estar desordenado (mezcla de C y C++). Hay casos raros de manejo de errores. De hecho, creo que puedo contar 3 declaraciones try-catch de todo el sistema. El código es complicado, las pérdidas de memoria son prominentes y encontrar un error es una aguja en un pajar. Hay cientos de líneas de código que pueden ser reemplazadas por funciones de C++. Yo diría que escribir el código es más eficiente, más limpio y más fácil de entender.

Desde mi experiencia, sí, por supuesto, puedes mezclar C y C++. Puedes hacer prácticamente lo que quieras, pero mantener, depurar y descubrir qué está pasando se convierte en un problema. Es fácil decir que va a limpiar sus asignaciones de memoria, pero tal vez otra persona use su código y no lo haga. Tal vez te olvidas de hacerlo y pierdes horas buscando bichos tontos, en lugar de usar ese tiempo para hacer algo productivo. Ni siquiera creo que deba haber una discusión. Cuando hagas C++, haz C++. Cuando haces C, do C.