¿Hay alguna razón para usar C ++ en lugar de C, Perl, Python, etc.? [cerrado]


164

Como desarrollador de Linux (lado del servidor), no sé dónde y por qué debería usar C ++.

Cuando voy por rendimiento, la primera y última opción es C.

Cuando el "rendimiento" no es el problema principal, los lenguajes de programación como Perl y Python serían buenas opciones.

Casi todas las aplicaciones de código abierto que conozco en esta área se han escrito en C, Perl, Python, script Bash, AWK o incluso PHP, pero nadie usa C ++.

No estoy discutiendo otras áreas como GUI o aplicaciones web, solo estoy hablando de Linux, CLI y demonios.

¿Hay alguna razón satisfactoria para usar C ++?


55
Solo considero C ++ debido a STL.
dan_waterworth

46
Entonces, algo que se puede hacer usando C, perl y python juntos se puede hacer usando C ++ solamente. ¿Y se pregunta por qué usar C ++?
Manoj R

36
«Cuando voy al rendimiento, la primera y la última opción es C.» sí, claro: D Esta es una afirmación no probada y trivialmente incorrecta.
deadalnix

16
@deadalnix: Yo no diría eso. C ++ tiene reglas complejas que podrían ser contraproducentes en el optimizador, porque no está permitido hacer algunas cosas. Y es súper fácil entrar en asesinos invisibles de rendimiento. Es bastante axiomático y, por lo tanto, cierto: D Aún en realidad, el código C ++ a veces será más rápido porque usará algoritmos y estructuras de datos más efectivos, y nadie optimiza el código C de todos modos. Entonces, cuando se hace correctamente, C ++ es C más seguro y más efectivo, y debe elegir C ++ sobre C cuando no hay problemas de compatibilidad o requisitos para el software de disponibilidad al 100%.
Codificador

44
La mejor razón, no considerada en las respuestas publicadas, se relaciona directamente con la pregunta de OP. DEPENDANCIAS !!!!, No es que su sistema promedio carezca de las bibliotecas de c ++, pero un sistema incorporado podría no tenerlas disponibles. La única forma de obtener su programa en todos los sistemas es escribir su programa en C. normal. Todo lo demás es solo debatir por qué no debe, o menos representado, usar C ++. Nada de eso aborda por qué C ++ no se usa con más frecuencia, y sin importar el mérito, la razón son las dependencias ... O y también el famoso c ++ rant de Linus.
JM Becker

Respuestas:


308

Cuando voy a actuar, la primera y última opción es C.

Y ahí es donde debes retroceder. Ahora, no puedo, en absoluto , hablar por el desarrollo del servidor. Quizás no haya una razón convincente para preferir C ++ sobre las alternativas.

Pero, en general, la razón para usar C ++ en lugar de otros lenguajes es el rendimiento. La razón de esto es que C ++ ofrece un medio de abstracción que, a diferencia de todos los otros lenguajes que conozco, no tiene sobrecarga de rendimiento en tiempo de ejecución.

Esto permite escribir código muy eficiente que todavía tiene un nivel de abstracción muy alto.

Considere las abstracciones habituales: funciones virtuales, punteros de función y el lenguaje PIMPL. Todos estos se basan en la indirección que se resuelve en tiempo de ejecución mediante la aritmética del puntero. En otras palabras, incurre en un costo de rendimiento (por pequeño que sea).

C ++, por otro lado, ofrece un mecanismo de indirección que no conlleva ningún costo (rendimiento): plantillas. (Esta ventaja se paga con un (a veces enormemente) mayor tiempo de compilación).

Considere el ejemplo de una función de clasificación genérica.

En C, la función qsorttoma un puntero de función que implementa la lógica por la cual los elementos se ordenan entre sí. La Arrays.sortfunción de Java viene en varias variantes; uno de ellos clasifica objetos arbitrarios y requiere Comparatorque se le pase un objeto que funcione de manera similar al puntero de función en C's qsort. Pero hay varias sobrecargas más para los tipos Java "nativos". Y cada uno de ellos tiene una copia propia del sortmétodo: una horrible duplicación de código.

Java ilustra una dicotomía general aquí: o tiene duplicación de código o incurre en una sobrecarga de tiempo de ejecución.

En C ++, la sortfunción funciona de manera similar qsorta C, con una diferencia pequeña pero fundamental: el comparador que se pasa a la función es un parámetro de plantilla . Eso significa que su llamada puede estar en línea . No es necesaria la indirección para comparar dos objetos. En un ciclo cerrado (como es el caso aquí), esto realmente puede hacer una diferencia sustancial.

No es sorprendente que la sortfunción C ++ supere a las C sortincluso si el algoritmo subyacente es el mismo. Esto es especialmente notable cuando la lógica de comparación real es barata.

Ahora, no digo que C ++ sea a priori más eficiente que C (u otros lenguajes), ni que a priori ofrezca una mayor abstracción. Lo que sí ofrece es una abstracción que es muy alta e increíblemente barata al mismo tiempo, por lo que a menudo no es necesario elegir entre un código eficiente y reutilizable.


16
Ahora sé lo suficiente sobre C ++ para saber si estás acertado o equivocado. Pero también quiero agregar que solo recibió 1 voto a favor, así que relájese. Esta es la Internet y suceden votos negativos. ¡Gran respuesta si es técnicamente sólido!
Chris

46
sin sobrecarga de rendimiento en tiempo de ejecución , eso no siempre es cierto. Si observa las implementaciones de vectores STL, verá que no aprovechan el uso de realloc () (no pueden debido a punteros, historia larga), mientras que todos los lenguajes de nivel superior que conozco pueden usar y usan realloc ( ) en el vector impl's. Este es solo un ejemplo de que no es tan obvio y todo en blanco y negro.
mojuba

19
@Jaroslaw, @Steve: pero lo mismo (= falta de código, falta de caché de instrucciones) es cierto para el código optimizado a mano que se adapta para cada tipo de datos (ver las diversas Arrays.sortimplementaciones de Java ). Solo tú pierdes la ventaja de la alta abstracción. Esta no es una desventaja específica de las plantillas, es una desventaja de la duplicación de código en general. Además, esto tiende a no importar, ya que en bucles cerrados, generalmente siempre se carga el mismo código.
Konrad Rudolph el

18
@Jaroslaw: lo curioso del caché de instrucciones es que es un caché . Es decir, no intenta almacenar todo , solo el código utilizado recientemente . Las plantillas pueden generar muchos códigos similares para diferentes tipos (un vector.push_backpara vector<int>y otro para vector<float>, pero mientras se trabaja con a vector<int>, hay pocas razones por las cuales el vector<float>código estaría en el caché de instrucciones. Así que no veo cómo eso realmente importa. La creación de instancias de plantillas individuales está altamente optimizada y, por lo general, es más compacta que las implementaciones genéricas genéricas
2010

29
@ Steve314: Lo que llama "hinchazón" es lo que se hace manualmente para C y Java. En C ++, se puede automatizar y los compiladores pueden ser tan inteligentes como los proveedores se atreven a hacer para evitar la hinchazón. Si tengo que decidir entre ser lento (como en C) o usar código duplicado (como en Java), hacer que el compilador haga la duplicación (y tal vez ser inteligente al respecto) parece bastante bueno, ¿no?
OSE

166

Veo demasiados programadores de C que odian C ++. Me llevó bastante tiempo (años) comprender lentamente qué es bueno y qué tiene de malo. Creo que la mejor manera de expresarlo es esta:

Menos código, sin gastos generales de tiempo de ejecución, más seguridad.

Cuanto menos código escribamos, mejor. Esto se aclara rápidamente en todos los ingenieros que luchan por la excelencia. Usted arregla un error en un lugar, no en muchos: expresa un algoritmo una vez y lo reutiliza en muchos lugares, etc. Los griegos incluso tienen un dicho, que se remonta a los antiguos espartanos: "decir algo en menos palabras, significa que eres sabio al respecto ". Y el hecho es que, cuando se usa correctamente , C ++ le permite expresarse en mucho menos código que C, sin costar la velocidad de tiempo de ejecución, a la vez que es más seguro (es decir, detecta más errores en tiempo de compilación) que C.

Aquí hay un ejemplo simplificado de mi renderizador : al interpolar valores de píxeles a través de la línea de exploración de un triángulo. Tengo que comenzar desde una coordenada X x1, y alcanzar una coordenada X x2 (desde el lado izquierdo al derecho de un triángulo). Y en cada paso, en cada píxel que paso, tengo que interpolar valores.

Cuando interpolo la luz ambiental que alcanza el píxel:

  typedef struct tagPixelDataAmbient {
      int x;
      float ambientLight;
  } PixelDataAmbient;

  ...
  // inner loop
  currentPixel.ambientLight += dv;

Cuando interpolo el color (llamado sombreado "Gouraud", donde los campos "rojo", "verde" y "azul" se interpolan por un valor de paso en cada píxel):

  typedef struct tagPixelDataGouraud {
      int x;
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  } PixelDataGouraud;

  ...
  // inner loop
  currentPixel.red += dred;
  currentPixel.green += dgreen;
  currentPixel.blue += dblue;

Cuando renderizo en el sombreado "Phong", ya no interpolo una intensidad (luz ambiental) o un color (rojo / verde / azul); interpolo un vector normal (nx, ny, nz) y en cada paso, tengo que volver -calcule la ecuación de iluminación, basada en el vector normal interpolado:

  typedef struct tagPixelDataPhong {
      int x;
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  } PixelDataPhong;

  ...
  // inner loop
  currentPixel.nX += dx;
  currentPixel.nY += dy;
  currentPixel.nZ += dz;

Ahora, el primer instinto de los programadores de C sería "diablos, escribir tres funciones que interpolan los valores y llamarlos según el modo establecido". En primer lugar, esto significa que tengo un problema de tipo: ¿con qué trabajo? ¿Mis píxeles son PixelDataAmbient? PixelDataGouraud? PixelDataPhong? Oh, espera, dice el eficiente programador C, ¡usa una unión!

  typedef union tagSuperPixel {
      PixelDataAmbient a;
      PixelDataGouraud g;
      PixelDataPhong   p;
  } SuperPixel;

..y luego, tienes una función ...

  RasterizeTriangleScanline(
      enum mode, // { ambient, gouraud, phong }
      SuperPixel left,
      SuperPixel right)
  {
      int i,j;
      if (mode == ambient) {
          // handle pixels as ambient...
          int steps = right.a.x - left.a.x;
          float dv = (right.a.ambientLight - left.a.ambientLight)/steps;
          float currentIntensity = left.a.ambientLight;
          for (i=left.a.x; i<right.a.x; i++) {
              WorkOnPixelAmbient(i, dv);
              currentIntensity+=dv;
          }
      } else if (mode == gouraud) {
          // handle pixels as gouraud...
          int steps = right.g.x - left.g.x;
          float dred = (right.g.red - left.g.red)/steps;
          float dgreen = (right.g.green - left.a.green)/steps;
          float dblue = (right.g.blue - left.g.blue)/steps;
          float currentRed = left.g.red;
          float currentGreen = left.g.green;
          float currentBlue = left.g.blue;
          for (j=left.g.x; i<right.g.x; j++) {
              WorkOnPixelGouraud(j, currentRed, currentBlue, currentGreen);
              currentRed+=dred;
              currentGreen+=dgreen;
              currentBlue+=dblue;
          }
...

¿Sientes el caos deslizándose?

En primer lugar, un error tipográfico es todo lo que se necesita para bloquear mi código, ya que el compilador nunca me detendrá en la sección "Gouraud" de la función, para acceder realmente al ".a". (ambiente) valores. Un error no detectado por el sistema de tipo C (es decir, durante la compilación) significa un error que se manifiesta en tiempo de ejecución y requerirá depuración. ¿ left.a.greenNotó que estoy accediendo en el cálculo de "dgreen"? El compilador seguramente no te lo dijo.

Luego, hay repetición en todas partes: el forbucle está allí tantas veces como haya modos de renderizado, seguimos haciendo "derecha menos izquierda dividida por pasos". Feo y propenso a errores. ¿Notó que comparo el uso de "i" en el bucle de Gouraud, cuando debería haber usado "j"? El compilador vuelve a estar en silencio.

¿Qué pasa con el if / else / ladder para los modos? ¿Qué sucede si agrego un nuevo modo de renderizado en tres semanas? ¿Recordaré manejar el nuevo modo en todos los "if mode ==" en todo mi código?

Ahora compare la fealdad anterior, con este conjunto de estructuras C ++ y una función de plantilla:

  struct CommonPixelData {
      int x;
  };
  struct AmbientPixelData : CommonPixelData {
      float ambientLight;
  };
  struct GouraudPixelData : CommonPixelData {
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  };
  struct PhongPixelData : CommonPixelData {
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  };

  template <class PixelData>
  RasterizeTriangleScanline(
      PixelData left,
      PixelData right)
  {
      PixelData interpolated = left;
      PixelData step = right;
      step -= left;
      step /= int(right.x - left.x); // divide by pixel span
      for(int i=left.x; i<right.x; i++) {
          WorkOnPixel<PixelData>(interpolated);
          interpolated += step;
      }
  }

Ahora mira esto. Ya no hacemos una sopa tipo union: tenemos tipos específicos para cada modo. Reutilizan sus cosas comunes (el campo "x") heredando de una clase base ( CommonPixelData). Y la plantilla hace que el compilador CREE (es decir, genere código) las tres funciones diferentes que habríamos escrito nosotros en C, pero al mismo tiempo, ¡es muy estricto con los tipos!

Nuestro bucle en la plantilla no puede funcionar y acceder a campos no válidos: el compilador ladrará si lo hacemos.

La plantilla realiza el trabajo común (el ciclo, que aumenta en "paso" cada vez), y puede hacerlo de una manera que simplemente NO PUEDE causar errores de tiempo de ejecución. La interpolación según el tipo ( AmbientPixelData, GouraudPixelData, PhongPixelData) se realiza con la operator+=()que vamos a añadir en las estructuras - que básicamente dictan cómo se interpola cada tipo.

¿Y ves lo que hicimos con WorkOnPixel <T>? ¿Queremos hacer un trabajo diferente por tipo? Simplemente llamamos una especialización de plantilla:

void WorkOnPixel<AmbientPixelData>(AmbientPixelData& p)
{
    // use the p.ambientLight field
}


void WorkOnPixel<GouraudPixelData>(GouraudPixelData& p)
{
    // use the p.red/green/blue fields
}

Es decir, la función a llamar se decide en función del tipo. ¡En tiempo de compilación!

Para reformularlo de nuevo:

  1. minimizamos el código (a través de la plantilla), reutilizando partes comunes,
  2. no usamos hacks feos, mantenemos un sistema de tipo estricto, para que el compilador pueda verificarnos en todo momento.
  3. y lo mejor de todo: nada de lo que hicimos tiene NINGÚN impacto en el tiempo de ejecución. Este código se ejecutará SOLO tan rápido como el código C equivalente; de ​​hecho, si el código C usaba punteros de función para llamar a las diversas WorkOnPixelversiones, el código C ++ será MÁS RÁPIDO que C, porque el compilador incorporará la WorkOnPixelespecialización de plantilla específica del tipo ¡llamada!

Menos código, sin gastos generales de tiempo de ejecución, más seguridad.

¿Significa esto que C ++ es el todo y el fin de todos los lenguajes? Por supuesto no. Todavía tiene que medir las compensaciones. Las personas ignorantes usarán C ++ cuando deberían haber escrito un script Bash / Perl / Python. Los novatos en C ++ que se desencadenan crearán clases anidadas profundas con herencia virtual múltiple antes de que pueda detenerlos y enviarlos a empacar. Utilizarán la metaprogramación Boost compleja antes de darse cuenta de que esto no es necesario. TODAVÍA usarán char*, strcmpy macros, en lugar de std::stringy plantillas.

Pero esto no dice nada más que ... mira con quién trabajas. No existe un lenguaje que lo proteja de usuarios incompetentes (no, ni siquiera Java).

Sigue estudiando y usando C ++, solo que no lo diseñes en exceso.


18
+1 para "no, ni siquiera Java" :)
Nathan Osman

53
+1 para el ejemplo. Fue una publicación larga, pero la comparación entre el código C y C ++ es impresionante.
paercebal

Y esto, damas y caballeros, es la razón por la que existe Lex / Yacc. El mismo razonamiento, nunca me di cuenta de que partes de c ++ caían en la misma filosofía de generación de código. Tendré que mirarlo de nuevo alguna vez.
Spencer Rathbun

2
He escrito mucho código de renderizado 2D (hace más de una década), y me encontré con este problema al portar de C a C ++: ¿cómo define una estructura de píxeles, si su línea de escaneo está hecha de píxeles de 1 bit (8 píxeles en un byte)? ¿Y cuando su línea de exploración está compuesta de bytes R, G y B (3 bytes por píxel)? ¿Y cuando tienes tres buffers separados para R, G y B? Ya sabes la respuesta: C ++ no sirve de nada, e insistir en usar plantillas te hará perder muchas optimizaciones de espacio y tiempo
Walter Tross

¿Por qué usas plantillas en C ++ para esto? Su método declara un parámetro de la clase base, por lo que desde mi punto de vista [programador de C #] parece que podría pasar la instancia de tipo derivado al parámetro de tipo base. No sé C ++, ¿podrías explicar por favor?
Vlad

79

RAII por la victoria bebé.

En serio, la destrucción determinista en C ++ hace que el código sea mucho más claro y seguro sin sobrecarga alguna.


20
"C ++: la única opción seriamente determinista. Pregúntele a su médico hoy".
Kyle Strand

2
Seguimiento: Rust ahora es un contendiente en este campo. Consulte un ejemplo básico de RAII y la documentación sobre los métodos destructores de Rust .
Kyle Strand

1
C será tan determinista, pero requiere más trabajo para asegurarse de que realmente sucede cuando se utiliza la memoria malloc-ed
Baldrickk

1
@Baldrickk en C tienes que escribir el código de limpieza donde sea que uses un recurso. En C ++, lo escribe una vez , en la definición del recurso. Tanto C como Java sufren de errores de "recurso utilizado después de desechado" y de "recurso de fuga", porque la limpieza no es automática . La memoria no es el único recurso.
Caleth

70

¿Hay alguna razón satisfactoria para usar C ++?

  1. Plantillas y el STL. Cambia un poco de tiempo de compilación (y algunos mensajes de error potencialmente incomprensibles) por muchas herramientas útiles de abstracción y ahorro de trabajo, sin un impacto apreciable en el rendimiento en tiempo de ejecución (aunque la huella binaria puede ser un poco mayor).

    Toma un tiempo entenderlo (me tomó un par de años antes de que hiciera clic), pero una vez que lo haces, la vida puede ser mucho más simple.

  2. El procesamiento de texto en C ++ es un orden de magnitud menos doloroso que en C.


35
+1 para el procesamiento de texto, que olvidé por completo en mi respuesta.
Konrad Rudolph

8
Je, me pareció especialmente doloroso el procesamiento de texto en comparación con Digamos que Python ..
Nils

77
Boost es la única razón por la que todavía uso C ++.
Ferruccio

33
@Nils: en una escala de 1 a dolor de cabeza, el procesamiento de texto en C ++ es definitivamente peor que en lenguajes más modernos como Python. Es solo que el procesamiento de texto en C define el dolor de cabeza. Si la elección es entre C y C ++ para esa aplicación en particular, entonces C ++ gana fácilmente.
John Bode

8
No sé por qué las personas tienen tanta dificultad con cosas como el procesamiento de texto en C / C ++. Solo usa una biblioteca o escribe la tuya. Una vez que ha escrito las funciones de bajo nivel (dolor único), obtiene un rendimiento masivo, un código estricto y una mayor flexibilidad. Sí, usaré Python para utilidades de línea de comando rápidas / sucias, pero para código de producción serio es C / C ++.

41

Si.

Si buscas eficiencia ejecutable, estás en C o C ++, así que me enfocaré en eso.

Incluso antes de que las plantillas fueran comunes, preferí usar C ++ sobre C para los tipos de ejecutables que discute a mediados de la década de 1990 por dos razones muy simples: polimorfismo de objetos y RAII .

He usado objetos polimórficos de C ++ para todo tipo de cosas interesantes. Por ejemplo, estaba trabajando en un sistema Linux incorporado con superposiciones de búfer de trama en CPU OMAP y XScale ARM. Las dos arquitecturas de hardware tienen características de superposición diferentes con API muy diferentes. Utilicé una clase base virtual "Overlay" común para exponer una vista idealizada de superposiciones, y luego escribí las clases "OmapOverlay" y "XScaleOverlay" que se instanciaron adecuadamente en tiempo de ejecución, dependiendo de la arquitectura en la que el código detectó que se estaba ejecutando.

Para simplificar demasiado, RAII es la idea de que asigna recursos conectados a un objeto durante el constructor del objeto, o tal vez más adelante en la vida útil del objeto, y los recursos se desasignan o liberan en el destructor del objeto. Eso es realmente bueno en C ++, porque los objetos que son variables automáticas se destruyen cuando salen del alcance. Para alguien que es igualmente competente en C y C ++, es mucho más fácil evitar las pérdidas de recursos y memoria en C ++. Tampoco verá mucho código C ++ con el meme C muy común de una etiqueta al final de una función que precede a un montón de llamadas a free(), y varias goto'' en el bloque de funciones saltando allí.

Soy plenamente consciente de que puede hacer todas estas cosas con C: es mucho más trabajo, muchas más líneas de código, y lo que termina es mucho más feo y, a menudo, más difícil de entender. Hay un código de polimorfismo en todos los componentes internos del servidor X , y hombre, es fugoso y extraño y con frecuencia difícil de rastrear.

También trabajo mucho con las tecnologías de GNOME como GTK + y Clutter, todas las cuales están escritas en C usando el sistema GObject. GObject es como el sistema de objetos C ++ con la bonita cubierta quitada y todas las partes internas feas expuestas, y generalmente requiere media docena de líneas de código para hacer lo que haría una llamada al método C ++ de una línea. Actualmente estoy escribiendo algunos ClutterActors, y aunque las matemáticas son realmente interesantes, pienso constantemente: "Todo esto sería mucho más conciso y comprensible en C ++".

También a menudo pienso: "Sabes, si estuviera escribiendo esto en C ++ en lugar de C, estaría en la sala viendo MythBusters con mi esposa en lugar de sentarme en mi oficina a las 9 PM".


99
Realmente puedo relacionarme con lo que estás diciendo aquí, especialmente 1) el punto sobre RAII y 2) el pensamiento "Sabes, si estuviera escribiendo esto en C ++ en lugar de C ..." hago mucho desarrollo de sistemas integrados , e incluso si el equipo es más o menos un tipo de tienda "C" o "C con clases", realmente trato de alentar a RAII para cosas como la manipulación de interrupciones, operaciones mutex y rastreo / registro (especialmente cosas como alternar E / S líneas). Y su descripción de las memorias intermedias de trama polimórficas me recordó mi uso de las memorias intermedias de mensajes polimórficos en un sistema distribuido.
Radian

29

C ++ es casi tan rápido como C (algunas cosas son más rápidas, otras más lentas) y ofrece mejores abstracciones y organización. Las clases funcionan de manera similar a los tipos primitivos, lo que permite utilizar grandes cantidades de código sin tener en cuenta. La sobrecarga del operador y las plantillas permiten escribir código que funciona mejor si cambian las representaciones de datos. Las excepciones pueden facilitar el manejo de errores. El compilador se puede usar para verificar más cosas en tiempo de compilación.

El precio que paga por esto es una curva de aprendizaje bastante desagradable, y es más fácil cometer errores sutiles que la mayoría de los otros idiomas con los que estoy familiarizado.

Por lo tanto, no puedo decir si valdría la pena que lo aprendas por lo que estás haciendo ahora. Ciertamente puede sobrevivir con combinaciones de Python o Perl y C, pero C ++ ofrece abstracción y rendimiento en un paquete difícil de acostumbrar.


13
No hay ningún caso en el que C ++ sea más lento que C porque siempre puedes usar el modo C si es más rápido (y te importa).
Jack Aidley

1
@JackAidley: excepto que C ++ no admite restricciones y parámetros de matriz estática. Y excepto que usar el estilo C ++ en un lugar te obliga a usarlo en otros lugares.
martinkunev

@martinkunev restrictse usa para hacer exclusiones de optimizaciones de alias, entonces, ¿cómo ayuda eso a acelerar las cosas ? ¿Y qué es un "parámetro de matriz estática"? ¿Y cómo afecta el "estilo" al rendimiento?
underscore_d

1
@underscore_d restrict permite optimizaciones, basadas en una garantía de no aliasing; Los parámetros de matriz estática permiten que el compilador suponga que un argumento de puntero no es NULL y que este puntero apunta al menos a un número dado de elementos; la palabra "estilo" tiene varios significados y ponerla fuera de contexto cambia su significado. Estoy hablando de cómo, por ejemplo, las excepciones imponen el uso de punteros inteligentes.
martinkunev

1
@martinkunev Hmm, así que me pregunto si un parámetro de matriz estática permite algo funcionalmente diferente de una plantilla de C ++ usando un T (&arr)[n]o std::array<T, n>- tendrá que investigar esto más, ya que no hay mucha información disponible. Eso tiene sentido sobre los punteros inteligentes, definitivamente un buen ejemplo. Si codificamos en un campo de juego igual, no usaríamos excepciones, por lo que no se incurriría en ninguno de los costos potenciales ... sin embargo, sospecho que podría estar aludiendo a cómo, una vez que las bibliotecas de terceros entran en escena, muchas suposiciones están en riesgo.
underscore_d

27

Considero C ++ como un lenguaje de la década de 1990, un lenguaje de una época pasada.

En aquel entonces era grande porque ofrecía construcciones y mecanismos de lenguaje de alto nivel a un costo menor en términos de rendimiento. Fue la herramienta universal para desarrollar todo, desde aplicaciones de libreta de direcciones hasta software de aviónica, y eso inspiró la locura OO. OOP resolvió el hambre y el SIDA, y sí, culpo a C ++ por tratar de lavarme el cerebro a fines de la década de 1990 cuando comencé a programar que no valía la pena aprender ningún lenguaje que no sea OO.

Ahora que el hardware ha avanzado tanto y han aparecido lenguajes modernos más nuevos, no veo que C ++ siga siendo una opción relevante para la mayoría de la programación de aplicaciones, excepto para el software computacionalmente intensivo donde todavía necesita algo de abstracción (juegos, simulaciones físicas, sistemas CAD, etc.) ) Incluso esto último se puede evitar si escribe un motor compacto y modular en C y tiene una lógica de aplicación de nivel superior delegada en un lenguaje de script ordenado.

Si necesita bajar al metal, use C sanamente, y cuando necesite ir a un nivel superior, hágalo en un lenguaje moderno que no anuncie la encapsulación mientras puede alterar libremente cada byte a través de un puntero.


11
Por lo tanto, no modifique bytes aleatorios con punteros. Eso no es tan difícil de evitar, ¿no?
David Thornley

11
@Blagovest: Estoy de acuerdo con usted sobre la complejidad de C ++ y nunca lo usaría para reemplazar un lenguaje orientado a objetos. Pero a pesar de su complejidad, todavía gana a C para mí debido a sus muchas ventajas explicadas en diferentes respuestas (abstracción, manejo de recursos, manejo de cadenas ...). De hecho, ha nombrado algunas áreas válidas donde C ++ sigue siendo relevante, y donde es muy superior a C.
Konrad Rudolph

66
@Blagovest: Por eso me mantengo fuera de los rincones oscuros. Es más fácil ser asaltado allí en C ++ que cualquier otro lenguaje que conozca. Al usarlo, me beneficio de RAII, un manejo de cadenas mucho mejor que C, las clases de plantillas de tipo STL, las características de OO y otras ventajas que tiene sobre C.
David Thornley

24
@Blagovest: No, no lo haces. Por ejemplo, lo que ha mencionado es insuficiente para lograr RAII, y las clases de contenedor tienen una funcionalidad que va más allá de las simples estructuras de datos hechas a mano. Si crees que es posible, nunca aprendiste bien C ++.
David Thornley

55
@Jaroslaw No veo por qué las máquinas multinúcleo llevarían a la OOP a la tumba. Si te refieres a C ++, podría ver de dónde vienes. OOP es un concepto fundamental en muchos lenguajes de programación modernos, especialmente lenguajes de alto nivel. Incluso C puede ser OO, si lo programa de esa manera. Simplemente no es tan conveniente como C ++ IMO.
vedosidad

21

Según Linus , no:

Cuando vi por primera vez el código fuente de Git, dos cosas me parecieron extrañas: 1. Pure C en lugar de C ++. No tengo idea de por qué. Por favor no hable de portabilidad, es BS.

USTEDES están llenos de mentiras.

C ++ es un lenguaje horrible. Se hace más horrible por el hecho de que muchos programadores de calidad inferior lo usan, hasta el punto de que es mucho más fácil generar basura total y absoluta con él. Francamente, incluso si la elección de C fuera hacer nada más que mantener alejados a los programadores de C ++, eso en sí mismo sería una gran razón para usar C.

En otras palabras: la elección de C es la única opción sensata. Sé que Miles Bader dijo en broma "para molestarte", pero en realidad es cierto. He llegado a la conclusión de que cualquier programador que prefieren que el proyecto sea en C ++ sobre C es probable que un programador que realmente me gustaría prefieren mear fuera, de modo que él no viene y arruinar cualquier proyecto que estoy involucrado con.

C ++ conduce a elecciones de diseño realmente muy malas. Invariablemente, comienza a utilizar las características "agradables" de la biblioteca del lenguaje como STL y Boost y otra basura total y total, que puede "ayudarlo" a programar, pero causa:

  • cantidades infinitas de dolor cuando no funcionan (y cualquiera que me diga que STL y especialmente Boost son estables y portátiles está tan lleno de BS que ni siquiera es gracioso)

  • modelos de programación abstractos ineficientes donde dos años más tarde notará que alguna abstracción no fue muy eficiente, pero ahora todo su código depende de todos los modelos de objetos agradables que lo rodean, y no puede solucionarlo sin reescribir su aplicación.

En otras palabras, la única forma de hacer C ++ bueno, eficiente, portátil y de nivel de sistema termina limitándose a todas las cosas que están básicamente disponibles en C. Y limitar su proyecto a C significa que las personas no lo arruinan y también significa que obtienes muchos programadores que realmente entienden los problemas de bajo nivel y no arruinan las cosas con ninguna basura idiota de "modelo de objetos".

Lo siento, pero para algo como git, donde la eficiencia era un objetivo principal, las "ventajas" de C ++ es solo un gran error. El hecho de que también molestemos a las personas que no pueden ver eso es solo una gran ventaja adicional.

Si quieres un VCS escrito en C ++, ve a jugar con Monotone. De Verdad. Usan una "base de datos real". Usan "buenas bibliotecas orientadas a objetos". Usan "buenas abstracciones de C ++". Y francamente, como resultado de todas estas decisiones de diseño que suenan tan atractivas para algunas personas de CS, el resultado final es un desastre horrible e imposible de mantener.

Pero estoy seguro de que te gustaría más que git.

      Linus

6262
No creo que Linus deba ser el tipo al que acudir para discutir aquí. Sus quejas son terriblemente subjetivas e inmaduras. En realidad, tiene algunos puntos buenos, pero están tan profundamente enterrados (debajo de la "mierda" y la mierda) que son muy difíciles de encontrar.
Konrad Rudolph

19
Jaja, esa fue una buena risa. Nunca quiero conocer a este chico.
Felix Dombek

30
Linus me recuerda a un techador muy talentoso que nunca colgó placas de yeso, pero llama a los muchachos de placas de yeso porque usan tornillos en lugar de clavos.
Bob Murphy

8
Linus tiene un punto, pero lo expresa con demasiada dureza para ser tomado en serio.
Blagovest Buyukliev

39
Estoy de acuerdo con @Daniel, si hay alguien que puede hablar sobre empujar los límites del hardware es John Carmack, creador de Doom, Quake y otros juegos y fundador del software Id. Él escribió esto sobre c y c ++ en un mensaje de Twitter hace unos meses: "En mi opinión, un buen código C ++ es mejor que un buen código C, pero un C ++ malo puede ser mucho, mucho peor que un código C malo". twitter.com/#!/ID_AA_Carmack/status/26560399301
Onema

18

No creo que haya ninguna razón convincente para usar C ++. Si desea hacer programación OO, puede usar Python en su lugar y escribir las partes que necesitan un rendimiento rápido en C.

EDITAR: Hay otros lenguajes que interactúan bien con C, por lo que si no te gusta Python, hay alternativas.


3
¿Qué pasa con el desarrollo integrado? Python no siempre está disponible, y la diferencia de velocidad entre C y C ++ bien escrita es insignificante en dispositivos que superan cierto nivel de potencia de procesamiento. Por supuesto, supongo que un compilador de C ++ tampoco estaría siempre disponible ...
James

66
@James "C ++ bien escrito" - ahí está el truco :(
dss539

55
Estoy de acuerdo con esta respuesta, haga el alto nivel con python, ya que lo escribirá algo 3 veces más rápido, perfilará y luego liberará cuellos de botella reemplazándolos con C / C ++. Es redundante decir "reemplazar cuello de botella con código C ++" ya que no hará ningún nivel alto con el código que necesita para ser rápido, ya que será un código de bajo nivel. Hay una cosa: no sé cómo interactuar c ++ con python: /. pero en términos de tiempo pasado frente a la pantalla y eficiencia, creo que esa es la mejor solución, ¡ya que la mayoría del código C ++ será rápido por nada!
jokoon

8
Vaya a trabajar para una gran compañía financiera y cree un sistema financiero complejo en un gran equipo distribuido en Python y vea cómo le gusta. La experiencia le enseñará: a) ventajas de la seguridad de tipos, b) ventajas de los compiladores que guardan su trasero, c) código LUDICOSO que Python permite que los novatos escriban. La gente dice que es fácil disparar el pie con C ++ -> algunas cosas de Python pueden funcionar, pero pueden ser una locura límite. En este momento preferiría trabajar en C ++ ...
MrFox

1
@suslik: Wow, estoy sorprendido de que alguien realmente use Python para ese tipo de sistema. Estoy de acuerdo con usted sobre el código de Python noob malo; Yo mismo he visto algunos.
Larry Coleman

13

¿Hay alguna razón para usar C ++? Ciertamente.

Algunas personas simplemente prefieren usar C ++ sobre otras opciones. Preguntar si hay una razón para usar C ++ es como preguntar por qué necesitamos tener cientos de sabores de helado. No a todos les gusta simplemente seguir con Vanilla.

Si los desarrolladores ya son muy competentes con C ++, la pregunta para ellos puede no ser "¿por qué usarlo?", Sino más bien "¿por qué no?". Parece que está sucediendo esta moda anti-C ++ en SO en este momento, pero lo creas o no, no todos se suscriben a eso. Algunas personas pueden simplemente preferir C ++ mejor que los otros lenguajes.

¿C ++ necesita ser usado para aplicaciones? Por supuesto no. Pero esta misma pregunta exacta también se puede hacer para cualquier otro idioma. Hay muy, muy pocos casos en los que un idioma en particular necesita ser usado para una aplicación.


12

Solo estoy cambiando de C a C ++, y creo que la ganancia es considerable, incluso si no necesita plantillas y POO.

  • Mejor gestión de la memoria.
  • Sistema de tipo más fuerte
  • Una mejor biblioteca estándar
  • Espacios de nombres
  • etc.

8

Me sorprende que nadie haya mencionado esto todavía, pero C ++ nos presentó referencias que casi resuelven todos los problemas y dificultades de los punteros:

void ModifyVar(int& var)
{
    var = 5;
}

int test = 4;
ModifyVar(test);

En lugar de:

void ModifyVar(int * var)
{
    *var = 5;
}

int test = 4;
ModifyVar(&test);

Mucho más seguro y más fácil también ... y sin la sobrecarga de pasar por valor.


3
También mucho menos flexible. Las referencias (estilo C ++) son buenas para simplificar ciertas construcciones comunes en un lenguaje que también tiene punteros, pero están lejos de ser un reemplazo para los punteros, ni siquiera es divertido. Y su ejemplo no es en absoluto un buen caso para referencias.
Ben Voigt

3
@Ben: Entonces, ¿puedes explicar por qué es un mal ejemplo?
Nathan Osman

66
@George: ¿Porque nada cambió, excepto que son dos (contarlos) caracteres más cortos? No está resolviendo ningún problema, no está destacando ningún escollo, ni siquiera hace nada bueno, como extender la vida útil de una variable temporal (en qué referencias son buenas).
Ben Voigt

@Ben: Estás olvidando algo, la referencia siempre es válida. Los punteros pueden apuntar a cualquier cosa (incluido NULL) que puede conducir a todo tipo de errores de memoria si las cosas no se hacen correctamente. Las referencias nunca pueden ser NULL y la dirección a la que apuntan nunca se puede cambiar.
Nathan Osman

55
@George: "la referencia siempre es válida" es completamente falsa. Le daré un ejemplo si lo necesita, pero espero que sea lo suficientemente experto como para darse cuenta de esto. Y tampoco estoy hablando de formar una referencia inválida usando un puntero inválido. Las funciones que usan punteros necesitan documentación que indique las condiciones previas de los argumentos. Pero en términos prácticos, todas las funciones necesitan ese nivel de documentación, por lo que es absurdo llamarlo un ataque contra los punteros.
Ben Voigt

5

El dónde y el por qué generalmente serán:

  • familiaridad
  • características del idioma deseado
  • bibliotecas específicas que desea usar
  • requisitos de desempeño

Para la programación del lado del servidor, a menudo puede elegir entre una miríada de idiomas diferentes, compilados o interpretados. Por lo general, la elección del idioma depende de la plataforma en la que usted o su equipo serán más efectivos. O si aún no tiene un equipo, la disponibilidad de habilidades en el mercado.

En una nota al margen, realmente no entiendo decidir usar C / C ++ basado en el rendimiento (solo) ya que muchos lenguajes de secuencias de comandos son extensibles con C / C ++. Obtiene el beneficio de un lenguaje de desarrollo rápido junto con la capacidad de migrar las porciones lentas a extensiones C / C ++. Ciertamente, si está haciendo programación de sistemas donde cada operación cuenta es comprensible, pero en la mayoría del desarrollo de aplicaciones no lo entiendo.


2
La familiaridad es la razón número 1, y me sorprende que seas el primero en mencionarlo.
Paul Butcher

4

C ++ vs Python vs Perl no se puede juzgar fácilmente. Depende del proyecto y los requisitos.

C ++ tiene un arsenal de utilidades de hace mucho tiempo, ejecutándose en muchas plataformas. Pero es doloroso comenzar a caminar a través de las corrientes simplemente pasando String a Integer y retrocediendo.

C ++, por otro lado, tiene un trato horrible con las dependencias de las bibliotecas. Una vez que compila algo en GCC X o VC ++ Y, no puede confiar en que el código se ejecutará en la próxima versión de esas herramientas. El mismo infierno está en Windows, el mismo infierno está en Unix también.

Perl, toma su poder del mundo Unix, pero especialmente como una herramienta de expresión regular. Esto es lo que se usa la mayor parte del tiempo. Junto con algunas herramientas bastante serias que incluso Java no puede hacerlo de manera normal (vea cómo cargar un archivo en un servidor web), Perl es "simplemente hágalo".

Python es un lenguaje fácil, flexible y dinámico. Tan fácil que puede enviar un número entero a una función, el script espera cadena, ¡pero puede obtener un resultado! Sin embargo, inesperado, pero un resultado. Por lo tanto, el programador debe ser muy cauteloso. IDLE ofrece algunas depuraciones, pero cuando ha conectado TELNET a un sistema, o ha ingresado SSH en tres niveles y desea encontrar su problema, el depurador no estará allí para estar junto a usted. Pero, puede hacer un gran trabajo matemático rápido.

Java es un ecosistema de palabras de moda, tecnologías extrañas y grandes palabras, y cuando solo desea cargar un archivo en el servidor web, descubre que solo puede hacerlo si el servidor tiene JSP . Si desea llamar a las bibliotecas del sistema o las funciones del sistema, como la supervisión, encontrará que tiene que cavar mucho. Y tal vez para llegar a JNI y OK ... piensas entonces ... "¿Por qué, Señor?"

Aparte de eso, Java es una gran herramienta para suites de negocios y multiproceso, me gustó mucho.

Rápido para hacer un programa y mostrarle a su CV "¡Oh, yo también conozco esa tecnología" y su aspirante a jefe, se sorprenderá! Aunque, la tecnología podría no ser tan necesaria ... (OK, amigos, odio el Spring Framework ...)


1
Por desgracia, debe tener en cuenta que Python tiene dependencias de versión, especialmente una vez que migra a Python 3, lo mismo con Perl ... ¿o alguien se ha molestado en pasar a Perl 6 todavía? Todo tiene dependencias desagradables :(
gbjbaanb

3

Lo que debe tener en cuenta al elegir un idioma es qué beneficio obtendrá al usarlo y cuánto tiempo llevará obtenerlo.

La idea principal entre lenguajes como Python y Perl es hacer más con menos tiempo de hombre, pero con más tiempo de CPU. De hecho, pasará más tiempo codificando un script de Python o Perl del que se ejecutará, pero entiendo mi punto.

La ventaja de C / C ++ es que son rápidos, pero a un costo de sintaxis y tipeo fuerte: debe hacer muchas cosas usted mismo para que la computadora no tenga que elegirlo en el momento de la compilación.

Cuando crea un código, algunas líneas se ejecutarán mucho más que otras, y esas líneas son las que plantean un problema. Por otro lado, todo el resto del código, en el que pasó mucho tiempo, se ejecuta con mucha menos frecuencia. Es posible que lo hayas escuchado, pero es la infame regla 80/20, y no podrás evitar esa regla.

La solución a este problema es usar un lenguaje más fácil (por más fácil quiero decir más amigable para el desarrollador: menos tipeo, interpretación perezosa, muchas rutinas y cosas preexistentes, etc.) para hacer todo su código.

Lo harás tan rápido en comparación con si lo hubieras hecho con C o C ++, habría tomado mucho más dolor de cerebro.

Su programa será lento, pero con un generador de perfiles, aísla la parte que se ejecuta el 80% del tiempo y las hace con C o C ++.

Al programar de esta manera, ahorró mucho tiempo y su programa es tan eficiente, tan rápido, tiene muchas menos posibilidades de perder memoria y ahorró tiempo.

Los lenguajes de script fueron diseñados para estar del lado del desarrollador, pero la optimización aún es posible. Por supuesto, puedes ser un mago de patrones de diseño o un vudú STL o incluso un guerrero cegador, y tal vez un monje haskell. Pero los idiomas nos hacen hablar con las computadoras, ¡los idiomas no están hechos para que seamos computadoras!



2

¡El C ++ que uso se llama C con clases!


8
Hurra, usaste la palabra clave 'clase'. ¡Ahora entiendes el diseño OO!
dss539

Mi C ++ se llama C con espacios de nombres.
jsz

66
Mi C ++ se llama, umm .. Manoj's C ++.
Manoj R

+1 lo clasifica como la única razón por la que uso C ++.
mbq

... ok, también excepciones.
mbq

0

En realidad, hay una sola respuesta a todas las preguntas formadas de esta manera. La mejor razón para usar tecnología X en lugar de tecnología Y (donde X e Y están aproximadamente en el mismo nivel [como casi todos los lenguajes de programación contemporáneos lo están]) es porque ya conoces X y no sabes Y.

(pero después de que Haskell llegó, no ha habido ninguna razón para usar otra cosa)


0

No, en absoluto. Si no necesita el rendimiento y hay una biblioteca que puede usar el otro idioma, no se moleste con C / C ++. Solo lo hago hoy en día cuando me dirijo a sistemas integrados que no pueden (¿fácilmente?) Ejecutar idiomas. A veces uso C porque estoy escribiendo un complemento, pero realmente no.

Sin embargo, no usaría Python, Perl, etc. para evitar el uso de C. Mi preferencia es en realidad C #, porque me gusta una buena biblioteca (que es una fortaleza de .NET), y me gustan los lenguajes estáticamente escritos. Boo es una buena alternativa. Pero realmente Haskell , OCaml , D , ML y demás están bien.


77
Te perdiste el punto.
Matt Joiner, el

@ Matt Joiner: Estoy seguro de que no. ¿Qué me perdí?

La pregunta es sobre no usar C ++.
Matt Joiner el

@ Matt Joiner: hmm, en otra mirada puedo ver que se lo pregunten. Pero parece que también respondí eso (dije que no te molestes y las alternativas que uso)

Casi quiero denunciar esto debido a C # ...
Vreality
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.