sintaxis - ¿Usando/Mezclando C en código C++?
sintaxis de c++ (12)
¿Está mal usar C en C ++?
Muchas personas me han dicho que el uso de C en C ++ es malo porque no es tan seguro y requiere más administración de memoria. Sigo diciéndoles que mientras sepas lo que estás haciendo, y eliminas tus "nuevas" y liberas tus "malloc", entonces C no es un problema.
Actualmente estoy en un foro donde se está desarrollando un argumento sobre std::string
vs. a char*
. Algunas personas dicen que asignar un bloque de memoria char*
simple es más eficiente, y mientras lo desasigne, está bien. Por otro lado, hay personas que dicen que std::string
es superior porque no tiene administración de memoria, pero es menos eficiente.
Así que la pregunta principal aquí es:
- ¿Es malo mezclar C / C ++? ¿Debería usar SOLAMENTE el 100% de C ++ cuando esté codificando C ++?
¡Cualquier respuesta sería apreciada!
¿Está mal usar C en C ++?
Aunque es una pregunta subjetiva: en mi opinión, tome grandes medidas para evitar el uso de programas c en c ++.
Muchas personas me han dicho que el uso de C en C ++ es malo porque no es tan seguro y requiere más administración de memoria. Sigo diciéndoles que siempre que sepas lo que estás haciendo, y eliminas tus novedades y liberas tus malloc''s, entonces C no es un problema.
está reintroduciendo 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 ++.
rutinariamente reviso / rechazo / reescribo el código que ingresa las bases de código que son "c con características de c ++", o "c ++ con c características". Incluso voy tan lejos como para cambiar malloc, free, etc. para afirmar en los espacios de nombres de raíz (entre otras cosas).
Actualmente estoy en un foro donde se está desarrollando un argumento sobre std :: string vs. a char *. Algunas personas dicen que asignar un bloque de memoria char * simple es más eficiente, y mientras lo desasigne, está bien. Por otro lado, hay 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 :: string.
en mi opinión, es completamente válido crear una nueva clase que represente una cadena y sirva para un propósito particular, o siga contratos adicionales (cuando sea necesario). parte de los contratos de tales representaciones de cadena son (por supuesto) que administran sus propios recursos usando el new[]/delete[]
cuando se utiliza la memoria dinámica.
Si la eficiencia es tan importante y std::string
es ideal para una tarea específica, entonces c ++ es lo suficientemente poderoso como para expresar su intención para estos casos específicos al crear una interfaz especializada en c ++. hay muchos casos en los que esto es aceptable (imo), pero no siempre vale la pena invertir el tiempo. en cualquier caso, es más fácil de administrar que la integración de expresiones / estilos / peligros en los programas de c ++.
Entonces la pregunta principal aquí es: ¿es malo mezclar C / C ++? ¿Debería utilizar ÚNICAMENTE el 100% de C ++ cuando codifique C ++?
Es mejor crear soluciones reutilizables basadas en objetos para sus necesidades. los peligros en el ejemplo proporcionado pueden ser completamente encapsulados (si esta optimización realmente vale la pena el tiempo invertido), y pueden escribirse para usar los lenguajes de c ++, sin pérdida de rendimiento y con una mejor capacidad de mantenimiento.
Sigo diciéndoles que siempre que sepas lo que estás haciendo, y eliminas tus novedades y liberas tus malloc''s, entonces C no es un problema.
Esto es verdad; Si tiene un cuidado extraordinario y se asegura de que limpia las cosas manualmente, entonces no es un problema. Pero, ¿realmente tienes tiempo para hacer eso? Cada llamada a new
puede lanzar std::bad_alloc
. ¿ Siempre detecta todas las excepciones que se pueden lanzar y limpia manualmente los recursos?
Me arriesgo a adivinar que la respuesta es "no", porque es muy tedioso escribir código como ese y es difícil estar absolutamente seguro de que el código escrito así sea correcto, incluso en el caso de fallas raras.
Si la respuesta es "sí", ¿por qué está perdiendo tanto tiempo preocupándose por la administración de recursos? Los modismos de C ++ como la gestión de recursos dependiente del alcance (SBRM; más comúnmente 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 tienes que hacerlo?
¿Debería usar SOLAMENTE el 100% de C ++ cuando codifique C ++?
Sí, aunque si hay una biblioteca de C que hace algo que necesita, o si tiene un código C heredado que desea usar, ciertamente puede usar ese código; Sólo asegúrese de tener cuidado. A menudo, la forma más limpia de interoperar con el código C es escribir un envoltorio de C ++ a su alrededor.
Bueno, estoy en una situación extraña. Estoy trabajando en un sistema que se supone que está en C ++ (se usa el compilador de 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 introduje std :: string. Mi opinión es que todo ahora está empezando a ser 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 está desordenado, las fugas de memoria son importantes 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, limpio y 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 realmente descubrir qué está pasando se convierte en un problema. Es fácil decir que va a limpiar sus asignaciones de memoria, pero tal vez alguien más use su código y no lo haga. Tal vez te olvidas de hacerlo y pierdes horas buscando insectos tontos, en lugar de usar ese tiempo para hacer algo productivo. Ni siquiera creo que deba haber una discusión. Cuando haces C ++, haz C ++. Cuando haces C, haz C.
Creo firmemente que su pregunta no tiene que ver con C o C ++ en absoluto. Su pregunta es sobre el comercio de dudosa eficiencia para la 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 contestar. En la mayoría de los casos, la sobrecarga de cadena contra const no es visible. Si está desarrollando una aplicación extremadamente crítica para la eficiencia, ¿por qué no codificarla en C en primer lugar?
En el caso específico de string
versus const char *
, debe usar bare const char *
para todas las variables que contengan constantes de string (y solo constantes de string), convirtiéndose en string
solo cuando se pasa a una API que requiere string
. Hacer esto de manera consistente puede eliminar una enorme cantidad de constructores globales, no causa problemas de asignación de memoria (ya que las constantes de cadena son permanentes, datos constantes) y IMO en realidad hace que el código sea más claro. Verá const char *
, sabe que será una cadena constante.
Estoy realmente sorprendido por la polarización en las respuestas y comentarios de los mismos.
En mis ojos, la respuesta es bastante simple:
Al escribir un proyecto en C ++, use C ++, evite C (y familia) y apéguese a la Biblioteca estándar y STL. Asegúrese de tener una interfaz de C ++ homogénea (¡es un proyecto de C ++, después de todo!) Cuando use un proyecto externo en C, que está escrito en C, por supuesto que puede usarlo. (ver ejemplos abajo)
Dos ejemplos principales:
Escribe un programa / biblioteca de C ++ que haga cálculos científicos. Definitivamente usaría GSL (Biblioteca Científica GNU), y está escrito en C. Solo hay algunas advertencias (como las funciones especializadas de inicialización y gratuitas para estructuras y funciones específicas dentro de GSL), que pueden ser absorbidas en un
std::unique_ptr
typedef. También está el problema del manejo de errores: la verificación de códigos de error se puede abstraer en un mecanismo de excepción si es necesario / deseable, o puede mantener los códigos de error contenidos dentro de las funciones de cálculo. GSL tiene una forma de configurar un controlador de errores, me imagino que algunas otras bibliotecas de C tienen esa funcionalidad.Escribiendo un programa en C ++ usando la API de Win32, que está horriblemente basada en C. Estoy hablando de un uso ligero de la API, como leer los archivos en un directorio, verificar si existe un archivo, etc., no 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 una
std::string
lugar de tener que pasar un búferchar*
como argumento.
Entiendo que ambos ejemplos son bastante ... poco profundos ... pero siento que expresan una idea lo suficientemente general.
La mejor pregunta aquí es, ¿por qué usar C? ¿El desempeño? En primer lugar, creo que no hay una diferencia de rendimiento medible para un programa con la misma función. En segundo lugar, tendría que hacer un perfil y probar que para su caso específico, C ++ es más lento. En tercer lugar, está renunciando a una gran cantidad de seguridad de la aplicación utilizando C en lugar de C ++.
La respuesta es, por supuesto: depende.
En general, usted quiere evitar mezclar cosas que puedan causar confusión, lo que puede llevar a errores más difíciles de encontrar. Solo porque "sabes lo que estás haciendo" no significa que la próxima persona que toque tu código sabrá lo que estabas haciendo. Si está desarrollando un código que solo utilizará alguna vez, entonces probablemente esté bien, pero rara vez es el caso.
Usar C para el rendimiento está bien si tienes cuidado. Pero solo debes hacerlo si SABES que necesitas el rendimiento. La optimización prematura de bajo nivel es el trabajo del diablo.
Es un caso muy raro en el que el uso de char * sobre std :: string le proporcionará beneficios notables en el rendimiento, y solo vale la pena la molestia de la administración de la memoria en aquellos casos en los que es seguro.
La respuesta simple aquí es, perfil ; ¡Determine cuál funciona mejor en su caso y úselo sabiamente!
Sí, es malo mezclar C y C ++, cualquier razón no tiene nada que ver con el rendimiento o la seguridad:
Es mala causa de una mantenibilidad:
* un 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 mezcla C ++ y C, rompe las expectativas de ambos programadores sobre cómo deberían funcionar las cosas.
Si estás hablando de técnicas, me atrevería a decir que hacer lo anterior está bien.
Escribir programas en C ++ usando técnicas de organización de programas de estilo C probablemente resultará en muchos problemas de mantenimiento. En general, el programador ignora muchos de los beneficios que proporciona un lenguaje orientado a objetos. Simplemente porque gran parte de la sintaxis de C es válida en C ++ y la transferencia de muchas técnicas de codificación no significa que deba hacerlo en C ++.
Dicho esto, el uso de las funciones de C y las cosas no es un problema, siempre que tenga cuidado con su uso. En algunos casos, tienes que hacerlo.
volviendo a calificar 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 un grupo de memoria privado. Y de todos modos, la robustez de la cadena std :: supera con creces a cualquier golpe imp (improbable)