C++

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 31 de julio de 2022; las comprobaciones requieren 14 ediciones .
C++
Semántica multi- paradigma : orientado a objetos , genérico , procedimental , metaprogramación
clase de idioma lenguaje de programación orientado a objetos , lenguaje de programación multiparadigma , lenguaje de programación procedimental , lenguaje de programación funcional , lenguaje de programación genérico , lenguaje de programación , lenguaje de forma libre [d] y lenguaje de programación compilado
tipo de ejecución compilado
Apareció en 1983
Autor Stroustrup, Bjorn
extensión de archivo .cc, .cpp, .cxx, .c, .c++, .h, .hpp, .hh, .hxxo.h++
Liberar
sistema de tipos estático
Implementaciones principales GNU C++ , Microsoft Visual C++ , Intel C++ compilador , Open64 C++ Compiler , Clang , Comeau C/C++ , Embarcadero C++ Builder , Watcom C++ compilador , Digital Mars C++, Oracle Solaris Studio C++ compilador, Turbo C++
Dialectos ISO/CEI 14882 C++
sido influenciado C , Simula , Algol 68 , Clu , ML y Ada
Sitio web isocpp.org
 Archivos multimedia en Wikimedia Commons

C ++ (pronunciado c-plus-plus [2] [3] ) es un lenguaje de programación de propósito general compilado , tipificado estáticamente .

Admite paradigmas de programación como la programación procedimental , la programación orientada a objetos y la programación genérica . El lenguaje tiene una rica biblioteca estándar que incluye contenedores y algoritmos comunes , E/S, expresiones regulares, compatibilidad con subprocesos múltiples y más. C++ combina características de lenguajes de alto y bajo nivel [4] [5] . En comparación con su predecesor, el lenguaje C  , se presta la mayor atención al soporte para la programación genérica y orientada a objetos [5] .

C++ es ampliamente utilizado para el desarrollo de software, siendo uno de los lenguajes de programación más populares [opiniones 1] [opiniones 2] . Su alcance incluye la creación de sistemas operativos , una variedad de programas de aplicación, controladores de dispositivos , aplicaciones para sistemas integrados, servidores de alto rendimiento y juegos de computadora. Hay muchas implementaciones del lenguaje C++, tanto gratuitas como comerciales, y para varias plataformas. Por ejemplo, en la plataforma x86 , estos son GCC , Visual C++ , Intel C++ Compiler , Embarcadero (Borland) C++ Builder y otros. C++ ha tenido un gran impacto en otros lenguajes de programación, sobre todo en Java y C# .

La sintaxis de C++ se hereda del lenguaje C. Uno de los principios de diseño originales era mantener la compatibilidad con C. Sin embargo, C++ no es estrictamente un superconjunto de C; El conjunto de programas que los compiladores de C y C++ pueden traducir igualmente bien es bastante grande, pero no incluye todos los programas de C posibles .

Historia

Etapa histórica de desarrollo [6] Año
lenguaje BCPL 1966
El lenguaje B (desarrollo original de Thompson bajo UNIX ) 1969
lenguaje C 1972
C con clases 1980
C84 1984
Frente (Edición E) 1984
frente (versión 1.0) 1985
Herencia múltiple/virtual 1988
Programación genérica ( plantillas ) 1991
ANSI C++ / ISO-C++ 1996
ISO/CEI 14882:1998 1998
ISO/CEI 14882:2003 2003
C++/CLI 2005
TR1 2005
C++11 2011
C++14 2014
C++17 2017
C++20 2020

Creación

El lenguaje se originó a principios de la década de 1980 , cuando el empleado de Bell Labs , Björn Stroustrup , ideó una serie de mejoras en el lenguaje C para sus propias necesidades [7] . Cuando Stroustrup comenzó a trabajar en Bell Labs a fines de la década de 1970 en problemas de la teoría de colas (aplicada al modelado de llamadas telefónicas), descubrió que los intentos de utilizar los lenguajes de modelado existentes en ese momento eran ineficaces y el uso de lenguajes de máquina altamente eficientes. fue demasiado difícil debido a su limitada expresividad. Por ejemplo, el lenguaje Simula tiene características que serían muy útiles para desarrollar software de gran tamaño, pero es demasiado lento, y el lenguaje BCPL es lo suficientemente rápido, pero demasiado parecido a los lenguajes de bajo nivel, y no es adecuado para desarrollar software de gran tamaño.

Recordando la experiencia de su disertación, Stroustrup decidió complementar el lenguaje C (el sucesor de BCPL) con las capacidades disponibles en el lenguaje Simula. El lenguaje C, siendo el lenguaje base del sistema UNIX en el que se ejecutaban las computadoras Bell, es rápido, rico en funciones y portátil. Stroustrup le agregó la capacidad de trabajar con clases y objetos. Como resultado, los problemas prácticos de modelado resultaron ser accesibles tanto en términos de tiempo de desarrollo (debido al uso de clases similares a Simula) como en términos de tiempo de cálculo (debido a la velocidad de C). Las primeras adiciones a C fueron clases (con encapsulación ), herencia de clases, verificación estricta de tipos, funciones en línea y argumentos predeterminados . Las primeras versiones del lenguaje, originalmente llamado "C con clases", han estado disponibles desde la década de 1980 .

Mientras desarrollaba C con clases , Stroustrup escribió el programa cfront  , un compilador que transforma el código fuente de C con clases en código fuente simple de C. Esto nos permitió trabajar en un nuevo lenguaje y usarlo en la práctica, usando la infraestructura ya disponible en UNIX para desarrollo en C. Un nuevo idioma, inesperadamente para el autor, ganó gran popularidad entre sus colegas y pronto Stroustrup ya no pudo apoyarlo personalmente, respondiendo miles de preguntas.

Para 1983, se agregaron nuevas funciones al lenguaje, como funciones virtuales, sobrecarga de funciones y operadores, referencias, constantes, control del usuario sobre la administración de memoria libre, verificación de tipos mejorada y un nuevo estilo de comentario ( //). El lenguaje resultante ya no es solo una versión aumentada del C clásico y ha sido renombrado de C con clases a "C++". Su primer lanzamiento comercial tuvo lugar en octubre de 1985 .

Antes del inicio de la estandarización oficial, el lenguaje fue desarrollado principalmente por Stroustrup en respuesta a las solicitudes de la comunidad de programación. La función de las descripciones del lenguaje estándar fue realizada por los trabajos impresos de Stroustrup en C ++ (una descripción del lenguaje, un manual de referencia, etc.). Recién en 1998 se ratificó el estándar internacional para el lenguaje C++: ISO/IEC 14882:1998 "Estándar para el lenguaje de programación C++"; después de la adopción de correcciones técnicas a la norma en 2003, la  siguiente versión de esta norma es ISO/IEC 14882:2003 [8] .

Desarrollo y estandarización del lenguaje

En 1985, salió la primera edición de The C++ Programming Language , brindando la primera descripción del lenguaje, lo cual fue sumamente importante debido a la falta de un estándar oficial. En 1989, se lanzó la versión 2.0 de C++. Sus nuevas características incluían herencia múltiple, clases abstractas, funciones de miembros estáticos, funciones constantes y miembros protegidos. En 1990, se publicó la "Guía de referencia comentada de C++", que luego se convirtió en la base del estándar. Las actualizaciones recientes han incluido plantillas, excepciones, espacios de nombres, nuevas conversiones y el tipo booleano. La biblioteca de plantillas estándar (STL) desarrollada por Alexander Stepanov y Meng Li fue elegida como base para almacenar y acceder a algoritmos genéricos .

La biblioteca estándar de C++ también ha evolucionado junto con ella. La primera adición a la biblioteca estándar de C++ fueron los flujos de E/S, que proporcionan un medio para reemplazar los C printfy scanf. Posteriormente, el desarrollo más significativo de la biblioteca estándar fue la inclusión de la Biblioteca de plantillas estándar .

C++ continúa evolucionando para cumplir con los requisitos modernos. Uno de los grupos que desarrolla el lenguaje C++ y envía propuestas para mejorarlo al comité de estandarización de C++ es Boost , que se dedica, entre otras cosas, a mejorar las capacidades del lenguaje añadiéndole características de metaprogramación .

Nadie posee los derechos del lenguaje C++, es gratuito. Sin embargo, el documento estándar de idioma en sí mismo (a excepción de los borradores) no está disponible gratuitamente [10] . Como parte del proceso de estandarización, ISO produce varios tipos de publicaciones. En particular, los informes técnicos y las especificaciones técnicas se publican cuando "el futuro está a la vista, pero no existe una posibilidad inmediata de acuerdo para la publicación de una norma internacional". Hasta 2011, se publicaron tres informes técnicos sobre C++: TR 19768: 2007 (también conocido como C++ Technical Report 1) para extensiones de biblioteca principalmente integradas en C++ 11, TR 29124: 2010 para funciones matemáticas especiales y TR 24733: 2011 para Aritmética de punto flotante decimal. Especificación técnica DTS 18822:. 2014 (por sistema de archivos) fue aprobado a principios de 2015, y el resto de las especificaciones están en desarrollo y en espera de aprobación [11] .

En marzo de 2016 se creó en Rusia el grupo de trabajo WG21 C++ . El grupo se organizó para recopilar propuestas para el estándar C++, presentarlas al comité y defenderlas en las reuniones generales de la Organización Internacional de Normalización (ISO) [12] .

Historia del nombre

El nombre de idioma resultante proviene del operador de incremento de posfijo C unario ++(incrementa el valor de una variable en uno). No se usó el nombre C+ porque es un error de sintaxis en C y, además, el nombre fue tomado por otro idioma. El lenguaje tampoco se llamó D porque " es una extensión de C y no intenta solucionar problemas eliminando elementos de C " [7] .

Filosofía de C++

En El diseño y la evolución de C++ [13] , Bjorn Stroustrup describe los principios que siguió al diseñar C++. Estos principios explican por qué C++ es como es. Algunos:

Descripción general del idioma

El estándar C++ consta de dos partes principales: una descripción del lenguaje principal y una descripción de la biblioteca estándar.

Al principio, el lenguaje se desarrolló fuera del marco formal, de manera espontánea, de acuerdo con las tareas a las que se enfrentaba. El desarrollo del lenguaje fue acompañado por el desarrollo del compilador cruzado cfront . Las innovaciones en el lenguaje se reflejaron en el cambio en el número de versión del compilador cruzado. Estos números de versión de compilador cruzado se extendieron al lenguaje en sí, pero las versiones de C ++ no se están discutiendo actualmente. No fue hasta 1998 que el idioma se estandarizó.

espacio de nombres Foo { constante int x = 5 ; } const int y = Foo :: x ;

Un espacio de nombres sin nombre es un caso especial. Todos los nombres descritos en él están disponibles solo en la unidad de traducción actual y tienen vinculación local. El espacio de nombres stdcontiene las bibliotecas estándar de C++.

  • newSe introducen los operadores , new[]y deletepara trabajar con memoria delete[]. A diferencia de la librería malloc y free que vino de C, estos operadores inicializan un objeto. Para clases, esta es una llamada de constructor, para tipos POD , la inicialización puede omitirse ( new Pod;) o inicializarse con valores cero ( new Pod(); new Pod {};).

Tipos

Los siguientes tipos integrados están disponibles en C++. Los tipos de C++ son casi idénticos a los tipos de datos de C :

  • carácter: char, wchar_t( char16_ty char32_t, en el estándar C++11 );
  • enteros con signo: signed char, short int, int, long int(y long long, en el estándar C++11 );
  • enteros sin signo: unsigned char, unsigned short int, unsigned int, unsigned long int(y unsigned long long, en el estándar C++11 );
  • coma flotante : float, double, long double;
  • booleano: boolque tiene los valores true, o false.

Los operadores de comparación devuelven el tipo bool. Las expresiones entre paréntesis después ifde , while se convierten al tipo bool[14] .

El lenguaje introdujo el concepto de referencias, y del estándar C++11 , rvalues ​​- referencias y referencias de reenvío .  (ver enlace (C++) )

C++ agrega características orientadas a objetos a C. Introduce clases que proporcionan las tres propiedades más importantes de OOP : encapsulación , herencia y polimorfismo .

En el estándar de C++, una clase es un tipo definido por el usuario declarado mediante una de las palabras clave o class, structuna unionestructura es una clase definida por struct, y una unión es una clase definida por union. Dependiendo de la palabra clave utilizada, algunas propiedades de la propia clase también cambian. Por ejemplo, en una clase declarada con struct, los miembros sin un modificador de acceso asignado manualmente serán públicos en lugar de privados de forma predeterminada.

En el cuerpo de una definición de clase, puede especificar tanto las declaraciones de función como su definición. En este último caso, la función es inline ( inline). Las funciones miembro no estáticas pueden tener consty calificadores volatile, así como un calificador de referencia ( &o &&).

Herencia

C++ admite la herencia múltiple . Las clases base (clases antepasadas) se especifican en el encabezado de la declaración de clase, posiblemente con especificadores de acceso. La herencia de cada clase puede ser pública, protegida o privada:

Modo de acceso/herencia de miembro de clase base miembro privado miembro protegido miembro público
herencia privada no disponible privado privado
herencia protegida no disponible protegido protegido
herencia pública no disponible protegido público

De forma predeterminada, la clase base se hereda como privada.

Como resultado de la herencia, la clase hija recibe todos los campos de las clases antecesoras y todos sus métodos; podemos decir que cada instancia de la clase descendiente contiene una sub- instancia de cada una de las clases antepasadas. Si una clase de antepasado se hereda varias veces (esto es posible si es el antepasado de varias clases base de la clase que se está creando), las instancias de la clase descendiente incluirán tantas subinstancias de esta clase de antepasado. Para evitar este efecto si no se desea, C++ soporta el concepto de herencia virtual . Al heredar, la clase base puede declararse virtual; para todas las instancias virtuales de la clase antecesora en el árbol de herencia de la clase descendiente, solo se crea una subinstancia en la descendiente.

Polimorfismo

C++ admite polimorfismo dinámico y polimorfismo paramétrico .

El polimorfismo paramétrico está representado por:

  • Argumentos predeterminados para funciones. Por ejemplo, para una función , void f(int x, int y=5, int z=10)las llamadas a y son equivalentes.f(1)f(1,5)f(1,5,10)
  • Sobrecarga de funciones : una función con el mismo nombre puede tener un número y tipo de argumentos diferente. Por ejemplo :voidPrint ( int x ) ; voidPrint ( doble x ) ; void Imprimir ( int x , int y );
La sobrecarga de operadores es un caso especial de sobrecarga de funciones .
  • motor de plantillas

El polimorfismo dinámico se implementa mediante métodos virtuales y una jerarquía de herencia. En C++, un tipo es polimórfico si tiene al menos un método virtual. Ejemplo de jerarquía:

figura de clase { público : sorteo de vacío virtual () = 0 ; // método virtual puro virtual ~ Figura (); // si hay al menos un método virtual, el destructor debe hacerse virtual }; plaza de clase : figura pública { público : void Dibujar () anular ; }; círculo de clase : figura pública { público : void Dibujar () anular ; };

Aquí la clase Figure es abstracta (e incluso clase de interfaz ), ya que el método Draw no está definido. No se pueden crear objetos de esta clase, pero se pueden utilizar referencias o punteros de tipo Figura. La elección de la implementación del método Draw se realizará en tiempo de ejecución en función del tipo real del objeto.

Encapsulación

La encapsulación en C++ se implementa especificando el nivel de acceso a los miembros de la clase: son públicos (public, public), protected ( protected) y private (private, private). En C++, las estructuras difieren formalmente de las clases solo en que, por defecto, el nivel de acceso a los miembros de la clase y el tipo de herencia para una estructura son públicos, mientras que para una clase son privados.

Acceso privado protegido público
La clase en sí
Amigos
herederos No
Desde afuera No No

La comprobación de acceso se produce en el momento de la compilación; intentar acceder a un miembro de clase inaccesible provocará un error de compilación.

Amigos

Las funciones amigas  son funciones que no son funciones miembro y, sin embargo, tienen acceso a miembros protegidos y privados de la clase. Deben declararse en el cuerpo de la clase como friend. Por ejemplo:

matriz de clase { amigo Matrix Multiply ( Matriz m1 , Matriz m2 ); };

Aquí, la función Multiplypuede acceder a cualquier campo y función miembro del Matrix.

Tanto la clase entera como una función miembro de la clase pueden ser declaradas amigas. Cuatro restricciones importantes en las relaciones de amistad en C++ son:

  • La amistad no es transitiva. Si A declara amigo de B, y B, a su vez, declara amigo de C, entonces C no se convierte automáticamente en amigo de A. Para hacer esto, A debe declarar explícitamente a C como amigo.
  • La amistad no es mutua. Si la clase A se declara amiga de la clase B, entonces no se convierte automáticamente en amiga de B. Para ello, debe haber una declaración explícita de simpatía de A en la clase B.
  • La amistad no se hereda. Si A declara a una clase B como amiga, entonces los hijos de B no se convierten automáticamente en amigos de A. Para hacer esto, cada uno de ellos debe ser declarado explícitamente amigo de A.
  • La amistad no se extiende a los descendientes. Si una clase A declara a B amigo, entonces B no se convierte automáticamente en amigo de las clases descendientes de A. Cada descendiente, si es necesario, debe declarar a B su propio amigo.

En general, esta regla se puede formular de la siguiente manera: "La relación de amistad existe solo entre aquellas clases (clase y función) para las que se declara explícitamente en el código, y actúa solo en la dirección en que se declara".

Características especiales

Una clase predeterminada puede tener seis funciones especiales: constructor predeterminado, constructor de copia, constructor de movimiento, destructor, operador de asignación de copia, operador de asignación de movimiento. También es posible definirlos todos explícitamente (ver la Regla de Tres ).

matriz de clase { público : Matriz ( ) = predeterminado // el compilador creará un constructor predeterminado de Array ( size_t _len ) : largo ( _largo ) { val = nuevo doble [ _len ]; } Array ( const Array & a ) = eliminar ; // copiar constructor eliminado explícitamente Array ( Array && a ); // mueve el constructor ~ Array () { eliminar [] valor ; } Array & operador = ( const Array & rhs ); // copiar operador de asignación Array & operator = ( Array && rhs ); // mueve el operador de asignación double & operator []( size_t i ) { valor de retorno [ i ]; } const double & operador []( size_t i ) const { valor de retorno [ i ]; } protegido : std :: size_t len ​​​​= 0 ; // inicialización de campo double * val { nullptr }; };

Se llama al constructor para inicializar el objeto (del tipo apropiado) cuando se crea, y se llama al destructor para destruir el objeto. Una clase puede tener varios constructores, pero un destructor solo puede tener uno. Los constructores en C++ no se pueden declarar virtuales, pero los destructores pueden declararse para todos los tipos polimórficos, y generalmente se declaran para todos los tipos polimórficos, para garantizar que un objeto referenciado o accesible por puntero se destruya correctamente, sin importar de qué tipo sea la referencia o el puntero. Si al menos una de las clases base tiene un destructor virtual, el destructor de la clase secundaria se vuelve virtual automáticamente.

Plantillas

Las plantillas le permiten generar funciones y clases que se parametrizan con un tipo o valor específico. Por ejemplo, la clase anterior podría implementar una matriz para cualquier tipo de datos:

plantilla < typenameT > _ matriz de clase { ... T & operador []( tamaño_t i ) { valor de retorno [ i ]; } protegido : std :: size_t len ​​{ 0 }; // inicialización de campo T * val { nullptr }; };

Biblioteca estándar

Estructura general

La biblioteca estándar de C++ incluye un conjunto de herramientas que deberían estar disponibles para cualquier implementación del lenguaje para proporcionar a los programadores un uso cómodo de las funciones del lenguaje y proporcionar una base para desarrollar una amplia gama de aplicaciones y bibliotecas especializadas. La biblioteca estándar de C++ incluye una parte de la biblioteca estándar de C. El estándar de C++ contiene una referencia normativa al estándar de C de 1990 y no define de forma independiente las funciones de biblioteca estándar que se toman prestadas de la biblioteca estándar de C.

#includeEl acceso a las capacidades de la biblioteca estándar de C++ se proporciona al incluir los archivos de encabezado estándar apropiados en el programa (a través de la directiva ). En total, 79 de estos archivos están definidos en el estándar C++11. Las instalaciones de la biblioteca estándar se declaran como parte del espacio de nombres estándar. Los archivos de encabezado cuyos nombres coinciden con el patrón "cX", donde X es el nombre del archivo de encabezado de la Biblioteca estándar de C sin extensión (cstdlib, cstring, cstdio, etc.), contienen declaraciones correspondientes a esa parte de la Biblioteca estándar de C. El C Las funciones de biblioteca estándar también se encuentran en el espacio de nombres estándar.

Composición

La biblioteca estándar incluye las siguientes secciones:

  • Soporte de idiomas . Incluye las herramientas necesarias para el funcionamiento de los programas, así como información sobre las funciones de implementación. Asignación de memoria, RTTI , excepciones básicas, límites de valor para tipos de datos numéricos, interacciones básicas del entorno como el reloj del sistema, manejo de señales UNIX, terminación de programas.
  • contenedores estándar . La biblioteca estándar incluye plantillas para los siguientes contenedores: matriz dinámica (vector), matriz estática (matriz), listas unidireccionales y bidireccionales (forward_list, list), stack (stack), deque (deque), matrices asociativas (mapa, multimapa), conjuntos (conjunto, multiconjunto), cola de prioridad (priority_queue).
  • Utilidades Básicas . Esta sección incluye una descripción de los principales elementos básicos utilizados en la biblioteca estándar, los asignadores de memoria y el soporte de fecha y hora de estilo C.
  • iteradores . Proporcione plantillas de iteradores que proporcionen un mecanismo estándar en la biblioteca estándar para aplicar algoritmos de procesamiento de datos en lotes a los elementos del contenedor.
  • algoritmos _ Plantillas para describir operaciones de procesamiento que, utilizando los mecanismos de la biblioteca estándar, se pueden aplicar a cualquier secuencia de elementos, incluidos los elementos en contenedores. En esta sección también se incluyen descripciones de las funciones bsearch() y qsort() de la biblioteca estándar de C.
  • cuerdas _ Plantillas de cadena de estilo C++. Esta sección también incluye algunas de las bibliotecas para trabajar con cadenas y símbolos de estilo C.
  • Entrada-salida . Plantillas y clases auxiliares para flujos de E/S generales, E/S de cadena, manipuladores (controles de formato de E/S de flujo de estilo C++).
  • localización _ Definiciones utilizadas para admitir nacionalidades de estilo C++ y estilo C y formatos de presentación (fechas, monedas, etc.).
  • diagnósticos _ Definiciones de una serie de excepciones y mecanismos de verificación de aserciones en tiempo de ejecución (afirmación). Compatibilidad con el manejo de errores de estilo C.
  • numeros _ Definiciones para trabajar con números complejos, vectores matemáticos, soporte para funciones matemáticas generales, generador de números aleatorios.

Los contenedores, cadenas, algoritmos, iteradores y utilidades básicas, con la excepción de los préstamos de la biblioteca C, se denominan colectivamente STL (Standard Template Library - biblioteca de plantillas estándar). Inicialmente, esta biblioteca era un producto separado y su abreviatura se descifraba de manera diferente, pero luego ingresó a la biblioteca estándar de C ++ como un elemento integral. El nombre refleja el hecho de que los mecanismos de programación generalizados (plantillas de C++ - plantilla) se utilizan para implementar herramientas de propósito general (contenedores, cadenas, algoritmos). Los escritos de Stroustrup detallan las razones por las que se hizo esta elección. Los principales son la mayor universalidad de la solución elegida (los contenedores de plantillas, a diferencia de los contenedores de objetos, se pueden usar fácilmente para tipos que no son objetos y no requieren un ancestro común para los tipos de elementos) y su eficiencia técnica (por regla general, los contenedores de plantillas las operaciones no requieren llamadas a funciones virtuales y se pueden incrustar fácilmente (en línea), lo que en última instancia proporciona una mejora en el rendimiento).

Comenzando con el estándar C++ 11, se han agregado las siguientes características:

  • Se ha agregado la biblioteca <regex>, que implementa mecanismos comunes de búsqueda y sustitución utilizando expresiones regulares.
  • Se agregó soporte para subprocesos múltiples.
  • Operaciones atómicas
  • variantes desordenadas de arreglos y conjuntos asociativos.
  • Punteros inteligentes que desasignan automáticamente la memoria asignada.

Implementaciones

El STL, antes de ser incluido en el estándar C++, fue un desarrollo de terceros, primero de HP y luego de SGI . El lenguaje estándar no lo llama "STL" ya que esta biblioteca se ha convertido en una parte integral del lenguaje; sin embargo, muchas personas todavía usan este nombre para distinguirlo del resto de la biblioteca estándar (Flujos de E/S ( iostream ), subsección C y otros).

Un proyecto llamado STLport [15] basado en SGI STL mantiene actualizadas las clases STL, IOstream y string. Varios otros proyectos también están desarrollando usos privados de la biblioteca estándar.

Diferencias con el lenguaje C

Compatibilidad con lenguaje C

La elección de C como base para crear un nuevo lenguaje de programación se explica por el hecho de que el lenguaje C:

  1. es un lenguaje polivalente, conciso y de nivel relativamente bajo;
  2. adecuado para la mayoría de las tareas del sistema;
  3. realizado en todas partes y en todo;
  4. interfaces con el entorno de programación UNIX.
— B. Stroustrup. Lenguaje de programación C++. Sección 1.6 [16]

A pesar de una serie de deficiencias bien conocidas del lenguaje C, Stroustrup eligió usarlo como base porque "C tiene sus problemas, pero un lenguaje diseñado desde cero los tendría, y conocemos los problemas de C". Además, esto nos permitió obtener rápidamente un prototipo de compilador ( cfront ) que solo traducía los elementos de sintaxis agregados al lenguaje C original.

A medida que se desarrollaba C++, se incluyeron otras características que anulan las capacidades de las construcciones de C, y se planteó repetidamente la cuestión de abandonar la compatibilidad del lenguaje mediante la eliminación de construcciones en desuso. Sin embargo, la compatibilidad se ha mantenido por las siguientes razones:

  • preservación del código actual, originalmente escrito en C y portado directamente a C ++;
  • eliminando la necesidad de volver a capacitar a los programadores que han estudiado previamente C (solo necesitan aprender nuevas herramientas de C++);
  • la eliminación de la confusión entre idiomas cuando se usan juntos ("si dos idiomas se usan juntos, sus diferencias deben ser mínimas o tan grandes que los idiomas no se pueden confundir").

Nuevas funciones

Las nuevas funciones de C++ incluyen declaraciones de expresiones, conversiones de tipos de funciones, operadores newy delete, tipo bool, referencias, constancia extendida, funciones en línea, argumentos predeterminados, anulaciones, espacios de nombres, clases (incluidas todas las funciones relacionadas con clases, como herencia, funciones miembro, funciones virtuales, funciones abstractas). clases y constructores ), anulaciones de operadores, plantillas, operadores ::, manejo de excepciones, identificación dinámica y más. El lenguaje C++ también es, en muchos casos, más estricto con respecto a la verificación de tipos que C.

C++ introdujo comentarios de doble barra ( //) que estaban en el predecesor de C, BCPL .

constAlgunas funciones de C++ se trasladaron posteriormente a C, como las palabras clave y , las inlinedeclaraciones de bucle fory los comentarios al estilo de C++ ( //). Las implementaciones posteriores de C también introdujeron características que no se encuentran en C++, como macros va_argy manejo mejorado de parámetros de matriz.

C++ no incluye C

Si bien la mayoría del código C también será válido para C++, C++ no es un superconjunto de C y no lo incluye. También hay algún código que es cierto para C pero no para C++. Esto lo distingue de Objective C , otra mejora de C para programación orientada a objetos , que es solo un superconjunto de C.

Hay otras diferencias también. Por ejemplo, C++ no permite llamar a una función main()dentro de un programa, mientras que en C es legal. Además, C++ es más estricto en algunos aspectos; por ejemplo, no permite la conversión implícita entre tipos de punteros no relacionados y no permite funciones que aún no se hayan declarado.

Además, el código que es válido para ambos idiomas puede producir resultados diferentes según el compilador del idioma al que se traduzca. Por ejemplo, en la mayoría de las plataformas, el siguiente programa imprime "C" si lo compila un compilador de C y "C++" si lo compila un compilador de C++. Esto se debe a que las constantes de caracteres en C (por ejemplo, 'a') son de tipo int, pero en C++ son de tipo chary los tamaños de estos tipos suelen diferir.

#incluir <stdio.h> int principal () { printf ( "%s \n " , ( tamaño de ( 'a' ) == tamaño de ( char )) ? "C++" : "C" ); devolver 0 ; }

C significa evitar

Como señala Stroustrup, "cuanto mejor conozca C, más difícil le resultará evitar programar en C++ al estilo de C, mientras pierde los beneficios potenciales de C++". Con ese fin, hace el siguiente conjunto de recomendaciones para que los programadores de C aprovechen al máximo C++:

  • No utilice macros #define. Para declarar constantes, utilice const, grupos de constantes (enumeraciones) - enum, para inclusión directa de funciones - inline, para definir familias de funciones o tipos - template.
  • No utilice declaraciones de variables hacia delante. Declarar variables en el bloque donde realmente se utilizan, combinando siempre declaración con inicialización.
  • Abandonar el uso de malloc()[17] a favor del operador new, de realloc()[18]  a favor del tipo vector. Será más seguro utilizar punteros inteligentes, como shared_ptry unique_ptr, disponibles a partir de la undécima versión del estándar.
  • Evite punteros sin tipo, aritmética de punteros, conversiones implícitas, uniones, excepto posiblemente en código de bajo nivel. Utilice conversiones de tipo "nuevas", ya que expresan con mayor precisión las intenciones reales del programador y son más seguras.
  • Minimice el uso de matrices y cadenas de caracteres de estilo C reemplazándolos con stringy vectordesde tipos STL. En general, no intente crear sus propias implementaciones de lo que ya está en la biblioteca estándar.

Mayor desarrollo

El estándar de idioma ISO/IEC 14882:2017 actual se publicó en diciembre de 2017 . Se le conoce extraoficialmente como C++17 . La próxima versión del estándar, prevista para 2020, tiene la designación no oficial C++20 .

Direcciones generales del desarrollo de C++

Según el autor del lenguaje, Björn Stroustrup [19] [20] [21] , al hablar sobre el desarrollo posterior y las perspectivas del lenguaje, se puede distinguir lo siguiente:

  • Básicamente, un mayor desarrollo del lenguaje seguirá el camino de hacer adiciones a la biblioteca estándar. Una de las principales fuentes de estos complementos es la famosa biblioteca Boost .
  • Los cambios en el núcleo del lenguaje no deberían reducir la eficiencia de C++ que ya se ha logrado. Desde el punto de vista de Stroustrup, es preferible hacer algunos cambios importantes en el núcleo que muchos cambios pequeños.
  • Las direcciones básicas para el desarrollo de C ++ en el futuro cercano son la expansión de las capacidades y el refinamiento de las herramientas de programación genéricas, la estandarización de los mecanismos de procesamiento paralelo, así como el refinamiento de las herramientas de programación seguras, como varios controles y seguridad. conversiones de tipos, comprobación de condiciones, etc.
  • En general, C++ está diseñado y desarrollado como un lenguaje multiparadigma que absorbe varios métodos y tecnologías de programación, pero los implementa en una plataforma que proporciona una alta eficiencia técnica. Por lo tanto, en el futuro, es posible que se agreguen al lenguaje herramientas de programación funcional, recolección automática de basura y otros mecanismos que actualmente están ausentes en él. Pero en cualquier caso, esto se hará sobre la plataforma existente de un lenguaje compilado altamente eficiente.
  • Aunque formalmente uno de los principios de C ++ sigue siendo mantener la compatibilidad con el lenguaje C, de hecho, los grupos de estandarización de estos lenguajes no interactúan, y los cambios que realizan no solo no se correlacionan, sino que a menudo se contradicen fundamentalmente. entre sí ideológicamente. Por lo tanto, los elementos que los nuevos estándares C agregan al kernel son elementos de la biblioteca estándar en el estándar C ++ y generalmente están ausentes en el kernel, por ejemplo, matrices dinámicas, matrices con límites fijos, instalaciones de procesamiento paralelo. Stroustrup cree que combinar el desarrollo de estos dos idiomas sería de gran beneficio, pero es difícilmente posible por razones políticas. Así que la compatibilidad práctica entre C y C++ se perderá gradualmente.

El estándar C++11: adiciones al núcleo del lenguaje

  • Funciones y expresiones constantes explícitamente definidas constexpr.
  • Inicialización genérica.
  • Constructores y operadores de asignación con semántica de transferencia.
  • Inferencia de tipo.
Para su uso en plantillas, donde es difícil especificar un tipo específico de variable, se han introducido dos nuevos mecanismos: variables de tipo autoy declaración decltype.
  • Recorra la colección.
Siguiendo muchos lenguajes modernos, C ++ introdujo la construcción de "bucle a través de la colección" del formulario for (type &x: array) {...}. Aquí, el cuerpo del bucle se ejecuta para cada elemento de la colección arrayy xen cada iteración se referirá al siguiente elemento de la colección. La colección puede ser una matriz C o cualquier contenedor de biblioteca estándar que defina iteradores beginy end.
  • Expresiones lambdas.
Se agregó la capacidad de declarar expresiones lambda (funciones sin nombre definidas en el punto de aplicación), incluidas aquellas que dependen de variables externas (cierres). Las expresiones lambda se pueden asignar a variables y se pueden usar donde se requiera una función del tipo correspondiente, como en los algoritmos de biblioteca estándar.
  • Cambios en la descripción de los métodos virtuales.
Se ha agregado un modificador opcional override, que se usa en la declaración de un método que reemplaza el método virtual de la clase padre. La descripción de la sustitución overrideprovoca una verificación de la presencia del método que se reemplaza en la clase principal y una coincidencia en las firmas del método. También se ha agregado un modificador final, como en Java, que prohíbe el reemplazo posterior del método marcado con él. finalTambién se puede declarar una clase; en este caso, está prohibido heredar nuevas clases de ella . Se define una palabra clave para una constante: un puntero nulo: nullptr. Se han realizado cambios en la semántica y, parcialmente, en la sintaxis de enumeraciones y uniones. Se ha agregado la capacidad de crear enumeraciones con seguridad de tipos, se han eliminado varias restricciones de estructura de las uniones. Se requiere que el compilador analice correctamente el texto del programa con varios corchetes angulares de cierre en una fila (anteriormente, la secuencia " >>" se percibía sin ambigüedades como una operación de desplazamiento a la derecha bit a bit, por lo tanto, en la notación de construcciones de plantillas anidadas, se requería separar los signos de “mayor que” con espacios o saltos de línea).

Ejemplos de programas

Ejemplo #1

Este es un programa de ejemplo ¡Hola, mundo! , que imprime un mensaje en la consola utilizando la biblioteca estándar y sale.

#incluir <iostream> utilizando el espacio de nombres estándar ; int principal () { cout << "¡Hola, mundo!" << endl ; devolver 0 ; }

Ejemplo #2

El C++ moderno le permite resolver problemas más complejos de forma sencilla. Este ejemplo demuestra, entre otras cosas, el uso de los contenedores de la biblioteca de plantillas estándar ( STL ).

#include <iostream> // para usar std::cout #include <vector> // contiene una matriz dinámica #include <mapa> // contiene el tipo de datos del diccionario #incluir <cadena> int principal () { // Importar todas las declaraciones del espacio de nombres "std" al espacio de nombres global. utilizando el espacio de nombres estándar ; // Declaramos un contenedor asociativo con claves de cadena y datos como vectores de cadena. mapa < cadena , vector < cadena > > elementos ; // Agrega un par de personas a este contenedor asociativo y dales algunos artículos. elementos [ "Anya" ]. push_back ( "bufanda" ); elementos [ "Dmitry" ]. push_back ( "boletos" ); elementos [ "Anya" ]. push_back ( "cachorro" ); // Recorrer todos los objetos en el contenedor for ( const auto & person : items ) { // persona es un par de dos objetos: persona.primero es su nombre, // persona.segundo es una lista de sus elementos (vector de cadenas) cout << persona . primero << " lleva " << persona . segundo _ tamaño () << "elementos" << endl ; } }

Este ejemplo importa todos los nombres del espacio de nombres estándar para simplificar. En un programa real, esto no se recomienda, ya que puede encontrar colisiones de nombres. El idioma le permite importar objetos individuales:

#incluir <vector> int principal () { usando std :: vector ; vector < int > mi_vector ; }

En C++ (como en C), si la ejecución del programa llega al final de la función main(), esto es equivalente a return 0;. Esto no es cierto para ninguna otra función que no sea main().

Comparación con lenguajes alternativos

Se conocen varios estudios en los que se ha intentado comparar de forma más o menos objetiva varios lenguajes de programación, uno de los cuales es C++. En particular:

  • En el artículo científico "Haskell vs. Ada contra C++ frente a Awk vs. …” Paul Hudak y Mark Jones [22] informan sobre el estudio de una serie de lenguajes imperativos y funcionales sobre la solución de un problema modelo de creación rápida de prototipos de un sistema GIS militar.
  • En el artículo científico “Implementación de DSL en metaocaml, template haskell, y C++” de cuatro autores [23] , se realiza un estudio metódico del uso de C++ y dos lenguajes funcionales como herramientas básicas para la programación orientada al lenguaje utilizando el método de programación generativa se lleva a cabo .
  • Lutz Prehelt [24] consideró siete lenguajes (C, C++, Java, Perl, Python, Rexx y Tcl) en la tarea de escribir un programa simple para convertir números telefónicos en palabras según ciertas reglas.
  • En el artículo de David Wheler "Ada, C, C++ y Java vs. Steelman [25] compara los lenguajes Ada, C++, C, Java con el documento " Steelman ": una lista de requisitos de lenguaje para el desarrollo militar de sistemas integrados, que fue desarrollada por el Comité de lenguaje de alto nivel de el Departamento de Defensa de los Estados Unidos en 1978. Si bien este documento está muy desactualizado y no tiene en cuenta muchas de las propiedades esenciales de los lenguajes modernos, la comparación muestra que C++, en términos del conjunto de características demandadas en la industria, no es tan diferente de los lenguajes que pueden ser considerados sus verdaderos competidores.
  • Un artículo de Matthew Forment y Michael Gillings [26] describe un estudio [27] de implementación en seis lenguajes —C++, C, C#, Java, Perl, Python— de tres algoritmos específicos utilizados en bioinformática: método del vecino más cercano , global alineación de secuencias ( algoritmo de Needleman-Wunsha ) y análisis de resultados BLAST .

C++ y Ada

El lenguaje Ada está cerca de C++ en términos de su conjunto de características y áreas de aplicación: es un lenguaje estructural compilado con una adición orientada a objetos similar a Simula (el mismo modelo de "Algol con clases" que en C++), escritura estática , herramientas de programación genéricas, diseñadas para el desarrollo de sistemas de software grandes y complejos. Al mismo tiempo, es fundamentalmente diferente en ideología: a diferencia de C ++, Ada se construyó sobre la base de condiciones cuidadosamente elaboradas previamente de fabricantes de software complejos con mayores requisitos de confiabilidad, lo que dejó una huella en la sintaxis y la semántica del idioma.

Hay pocas comparaciones directas de la eficiencia de codificación de Ada y C++. En el artículo [22] mencionado anteriormente, la solución del problema del modelo en Ada resultó en un código aproximadamente un 30% más pequeño en tamaño (en líneas) que en C++. La comparación de las propiedades de los propios idiomas se encuentra en muchas fuentes, por ejemplo, el artículo de Jim Rogers sobre AdaHome [28] enumera más de 50 puntos de diferencias en las propiedades de estos idiomas, la mayoría de los cuales están a favor de Ada. (más funciones, comportamiento más flexible, menos posibilidades de errores). Aunque muchas de las declaraciones de los seguidores de Ada son controvertidas, y algunas de ellas están claramente desactualizadas, en general se puede concluir:

  • La sintaxis de Ada es mucho más estricta que la de C++. El lenguaje requiere adherirse a la disciplina de la programación, no fomenta los "trucos de programación", fomenta la escritura de código simple, lógico y fácil de entender y fácil de mantener.
  • A diferencia de C++, Ada es extremadamente seguro para los tipos. Un sistema desarrollado de tipos permite, sujeto a la disciplina de su declaración y uso, controlar estáticamente la corrección del uso de datos de la manera más completa posible y protege contra errores accidentales. Las conversiones automáticas de tipo se reducen al mínimo.
  • Los punteros en Ada están mucho más controlados que en C++, y la aritmética de direcciones solo está disponible a través de una biblioteca de sistema separada.
  • Los módulos personalizados de Ada son similares en funcionalidad a las plantillas de C++, pero brindan un mejor control.
  • Ada tiene una modularidad integrada y un sistema de compilación independiente estandarizado, mientras que C++ utiliza la inclusión de archivos de texto y compilación externa y controles de compilación.
  • La multitarea integrada de Ada incluye tareas paralelas y su mecanismo de comunicación (entradas, encuentro, operador select). En C++, todo esto se implementa solo a nivel de biblioteca.
  • Ada está estrictamente estandarizado, por lo que proporciona una mejor portabilidad.

En un artículo de Stephen Zeiger de Rational Software Corporation [29] , se afirma que el desarrollo en Ada es generalmente un 60% más barato y da como resultado un código con 9 veces menos defectos que en C. Aunque estos resultados no se pueden transferir directamente a C++, siguen siendo interesantes dado que muchas de las deficiencias de C++ se heredan de C.

C++ y Java

Java no puede considerarse un reemplazo completo de C++, está diseñado como un lenguaje seguro con un umbral de entrada bajo para desarrollar aplicaciones personalizadas con alta portabilidad [30] y es fundamentalmente inadecuado para algunos tipos de aplicaciones que se desarrollan en C++. Sin embargo, dentro de su alcance, Java es un competidor muy real de C++. Los beneficios de Java se citan comúnmente como:

  • Seguridad: sin soporte para punteros y aritmética de direcciones, administración automática de memoria con recolección de elementos no utilizados, protección integrada contra errores comunes del programa C++, como desbordamientos de búfer o desbordamientos de matrices.
  • La presencia de un sistema desarrollado de módulos y compilación separada, mucho más rápido y menos propenso a errores que el preprocesador y el ensamblaje manual de C ++.
  • Estandarización completa y ejecución en una máquina virtual, un entorno desarrollado, que incluye bibliotecas para gráficos, interfaz de usuario, acceso a bases de datos y otras tareas típicas, como resultado: multiplataforma real.
  • Multiproceso incorporado.
  • El subsistema de objetos de Java, en un grado mucho mayor que el de C++, se ajusta al principio fundamental de programación orientada a objetos " todo es un objeto ". Las interfaces le permiten brindar la mayoría de los beneficios de la herencia múltiple sin causar sus efectos negativos.
  • Reflection es mucho más avanzado que en C++ y le permite definir y cambiar la estructura de los objetos mientras se ejecuta el programa.

Al mismo tiempo, el uso del recolector de basura y la máquina virtual crean limitaciones que son difíciles de superar. Los programas Java tienden a ser más lentos, requieren mucha más memoria y la máquina virtual aísla el programa del sistema operativo, lo que hace imposible la programación de bajo nivel.

Un estudio empírico [24] no encontró diferencias significativas en la velocidad de desarrollo en C++ y Java. El estudio [26] también mostró que la idea de una diferencia significativa en la velocidad de los programas en estos lenguajes no siempre es correcta: en dos de cada tres pruebas, la velocidad de las aplicaciones en Java y C++ resultó ser comparable. Al mismo tiempo, Java es más conciso: la diferencia en la cantidad de código fue de un 10-15 %.

C++ y C

El C original continúa evolucionando, se están desarrollando muchos proyectos a gran escala en él: es el lenguaje principal para desarrollar sistemas operativos, los motores de juego de muchos juegos dinámicos y una gran cantidad de aplicaciones de aplicación están escritas en él. Varios expertos argumentan que reemplazar C con C ++ no aumenta la eficiencia del desarrollo, sino que genera una complicación innecesaria del proyecto, reduce la confiabilidad y aumenta los costos de mantenimiento. En particular:

  • Según Linus Torvalds, "C++ provoca la escritura... una cantidad significativa de código que no tiene una importancia fundamental en términos de la funcionalidad del programa" [opiniones 3] .
  • El soporte de programación orientada a objetos, las plantillas y STL no son una ventaja decisiva de C ++, ya que todo para lo que se utilizan también se implementa utilizando herramientas de C. Al mismo tiempo, se elimina la sobreinflación del código y se compensa cierta complicación, que además dista mucho de ser necesaria, con una mayor flexibilidad, pruebas más sencillas y mejores indicadores de rendimiento.
  • La automatización del acceso a la memoria en C++ aumenta los costos de memoria y ralentiza los programas.
  • El uso de excepciones de C++ lo obliga a seguir RAII , conduce al crecimiento de los archivos ejecutables y ralentiza los programas. Surgen dificultades adicionales en los programas paralelos y distribuidos. Significativamente, el estándar de codificación C++ de Google prohíbe expresamente el uso de excepciones [31] .
  • El código C++ es más difícil de entender y probar, y la depuración se hace más difícil por el uso de jerarquías de clases complejas con comportamiento y herencia de plantillas. Además, hay más errores en los entornos de programación C++, tanto en compiladores como en bibliotecas.
  • El estándar C++ no especifica muchos detalles del comportamiento del código, lo que perjudica la portabilidad y puede causar errores difíciles de encontrar.
  • Hay programadores significativamente más hábiles en C que en C++.

No hay evidencia convincente de que C++ sea superior a C en términos de productividad del programador o propiedades del programa. Aunque hay estudios [32] que indican que los programadores de C dedican alrededor del 30-40 % del tiempo total de desarrollo (excluyendo la depuración) a la gestión de la memoria, cuando se compara la productividad general de los desarrolladores [22] , C y C++ están cerca.

En la programación de bajo nivel, muchas de las nuevas funciones de C++ se vuelven inaplicables debido al aumento de la sobrecarga: las funciones virtuales requieren un cálculo dinámico de direcciones reales (RVA), las plantillas conducen a una sobrecarga de código y capacidades de optimización deficientes, la biblioteca en tiempo de ejecución (RTL) es muy grande, y su rechazo priva a la mayoría de las funciones de C ++ (aunque solo sea por la falta de disponibilidad de las operaciones new/ delete). Como resultado, el programador deberá limitarse a la funcionalidad heredada de C, lo que hace que no tenga sentido usar C ++:

… la única forma de tener un C++ portátil bueno, eficiente y de bajo nivel es limitarse a todas las cosas que están trivialmente disponibles en C. Y limitar el proyecto a C significará que la gente no lo tirará, y que habrá muchos programadores disponibles que realmente entiendan bien las funciones de bajo nivel y no las abandonen debido al idiota "modelo de objetos". disparates.
… cuando la eficiencia es primordial, las "ventajas" de C++ serán un gran error.

Linus Torvalds , [33]

C++ y lenguajes funcionales y de script

En un experimento [22] , los lenguajes funcionales y de secuencias de comandos, en particular Haskell , mostraron una ganancia de 2 o 3 veces en el tiempo de programación y el tamaño del código en comparación con los programas C++. Por otro lado, los programas en C++ resultaron ser mucho más rápidos. Los autores reconocen que sus datos no constituyen una muestra representativa y se abstienen de sacar conclusiones categóricas.

En otro experimento [34] , los lenguajes funcionales estrictos ( Standard ML , OCaml ) mostraron una aceleración general del desarrollo por un factor de 10 (principalmente debido a la detección temprana de errores) con indicadores de rendimiento aproximadamente iguales (muchos compiladores en varios modos fueron usó).

En un estudio de Lutz Prehelt [24] , basado en los resultados del procesamiento de unas 80 soluciones escritas por voluntarios, se obtuvieron las siguientes conclusiones, en particular:

  • Perl, Python, Rexx, Tcl proporcionaron el doble de velocidad de desarrollo que C, C++ y Java, y el código resultante también fue la mitad de largo.
  • Los programas en lenguajes de secuencias de comandos consumían aproximadamente el doble de memoria que C/C++

Crítica

Sobre las críticas a C++ en general

La mayoría de las veces, los críticos no oponen C++ a ningún otro lenguaje específico, pero argumentan que el rechazo de usar un solo lenguaje que tiene numerosos defectos a favor de descomponer un proyecto en subtareas que pueden resolverse en varios lenguajes que son más adecuados para ellos hace que el desarrollo consuma significativamente menos tiempo, al tiempo que mejora los indicadores de calidad de la programación [35] [36] . Por la misma razón, se critica mantener la compatibilidad con C: si una parte de la tarea requiere características de bajo nivel, es más razonable separar esta parte en un subsistema separado y escribirlo en C.

A su vez, los partidarios de C ++ afirman que la eliminación de los problemas técnicos y organizativos de la interacción entre lenguas mediante el uso de un lenguaje universal en lugar de varios especializados es más importante que las pérdidas por la imperfección de este lenguaje universal, es decir, el la gran amplitud del conjunto de funciones de C ++ es una excusa para las deficiencias de cada función individual; incluso las desventajas heredadas de C se justifican por las ventajas de la compatibilidad (ver arriba ).

Por lo tanto, las mismas propiedades de C ++ (volumen, complejidad, eclecticismo y falta de un nicho de aplicación objetivo específico) son consideradas por los partidarios como "la principal ventaja ", y por los críticos, como " la principal desventaja ".

Crítica de elementos y conceptos individuales

Control de comportamiento

La ideología del lenguaje confunde el " control de comportamiento " con el " control de eficiencia ": el principio " no pagas por lo que no usas " sugiere que proporcionar al programador un control completo sobre todos los aspectos de la ejecución del programa en un nivel bastante bajo es una condición necesaria y suficiente para lograr una alta eficiencia del código. De hecho, esto no es cierto para ningún programa grande: imponer una optimización de bajo nivel en el programador, que un compilador de lenguaje específico de dominio de alta calidad obviamente puede realizar de manera más eficiente, solo conduce a un aumento en la cantidad de código, un aumento en la intensidad del trabajo de programación y una disminución en la comprensión y capacidad de prueba del código. Así, el principio de “no pagar por lo que no se usa” realmente no proporciona los beneficios deseados en eficiencia, sino que afecta negativamente a la calidad.

Programación orientada a objetos y componentes

Según Alan Kay , el modelo de objeto " Algol con clases" utilizado en C++ es inferior al modelo "todo es un objeto" [37] utilizado en Objective-C en términos de alcance general, reutilización de código , comprensibilidad, modificabilidad y comprobabilidad. .

El modelo de herencia de C++ es complejo, difícil de implementar y, al mismo tiempo, provoca la creación de jerarquías complejas con relaciones no naturales entre clases (por ejemplo, herencia en lugar de anidamiento). El resultado es la creación de clases estrechamente acopladas con funciones vagamente separadas. Por ejemplo, en [38] se da un ejemplo educativo y de recomendación de la implementación de la clase "lista" como una subclase de la clase "elemento de lista" que, a su vez, contiene funciones de acceso para otros elementos de lista. Esta relación de tipos es matemáticamente absurda e irreproducible en lenguajes más rigurosos. La ideología de algunas bibliotecas requiere la conversión manual de tipos hacia arriba y hacia abajo en la jerarquía de clases ( static_casty dynamic_cast), lo que viola la seguridad de tipos del lenguaje. La alta viscosidad de las soluciones de C++ puede requerir que se vuelvan a desarrollar grandes porciones del proyecto con cambios mínimos más adelante en el proceso de desarrollo. Un vívido ejemplo de tales problemas se puede encontrar en [35]

Como señala Ian Joyner [39] , C++ erróneamente equipara la encapsulación (es decir, colocar datos dentro de objetos y separar la implementación de la interfaz) y la ocultación de la implementación. Esto complica el acceso a los datos de la clase y requiere que su interfaz se implemente casi exclusivamente a través de funciones de acceso (lo que, a su vez, aumenta la cantidad de código y lo complica).

La coincidencia de tipos en C++ se define a nivel de identificadores, no de firmas. Esto hace que sea imposible reemplazar los componentes basados ​​en la coincidencia de la interfaz, por lo que la inclusión de una nueva funcionalidad implementada a nivel de biblioteca en el sistema requiere la modificación manual del código existente [40] . Como señala Linus Torvalds [33] , en C++, "el código parece abstracto solo mientras no sea necesario cambiarlo".

La crítica de C++ desde el punto de vista de OOP se da en [39] .

Metaprogramación

La metaprogramación generativa de C++ está basada en plantillas y preprocesadores , requiere mucha mano de obra y tiene un alcance limitado. El sistema de plantillas de C++ es en realidad una variante en tiempo de compilación del lenguaje de programación funcional primitivo. Este lenguaje casi no se superpone con el propio C ++, por lo que el potencial de crecimiento en la complejidad de las abstracciones es limitado. Los programas que utilizan plantillas de C++ tienen una comprensión y una capacidad de prueba extremadamente bajas, y el propio desenvolvimiento de la plantilla genera un código ineficiente, ya que el lenguaje de la plantilla no proporciona ningún medio para la optimización (consulte también la sección #Eficiencia informática ). Los lenguajes específicos de dominio integrados implementados de esta manera aún requieren el conocimiento de C ++ en sí mismo, lo que no proporciona una división del trabajo completa. Por lo tanto, la capacidad de C++ para ampliar las capacidades de C++ en sí es bastante limitada [41] [42] .

Multiplataforma

Escribir código C++ portátil requiere mucha habilidad y experiencia, y es muy probable que el código C++ "descuidado" no sea portátil [43] . Según Linus Torvalds , para lograr una portabilidad de C++ similar a la de C, el programador debe limitarse a las características de C++ heredadas de C [33] . El estándar contiene muchos elementos definidos como "definidos por la implementación" (por ejemplo, el tamaño de los punteros a métodos de clase en diferentes compiladores varía de 4 a 20 bytes [44] ), lo que empeora la portabilidad de los programas que los utilizan.

La naturaleza directiva de la estandarización del lenguaje , la retrocompatibilidad incompleta y la inconsistencia de los requisitos de las diferentes versiones del estándar generan problemas en la transferencia de programas entre diferentes compiladores e incluso versiones de los mismos compiladores.

Falta de oportunidades

Metaprogramación reflexiva La introspección en C++ se implementa por separado del sistema de tipo principal, lo que lo hace casi inútil. Lo máximo que se puede obtener es la parametrización del comportamiento sobre un conjunto de opciones previamente conocidas. Esto evita el uso de C++ en la mayoría de los enfoques para la implementación de inteligencia artificial . Programación funcional El soporte explícito para la programación funcional está presente solo en el estándar C ++ 0x , anteriormente el vacío se llenó con bibliotecas ( Loki , Boost ) que usan el lenguaje de plantilla, pero su calidad es significativamente inferior a las soluciones integradas en lenguajes funcionales [explicaciones 1] , así como la calidad de las implementaciones de características de C++ (como OOP) a través de lenguajes funcionales. Las capacidades de FP implementadas en C++ no permiten el uso de técnicas de optimización inherentes a la programación funcional , sino que se limitan a llamar a bibliotecas funcionales e implementar métodos individuales. Esto tiene poca o ninguna ventaja en el diseño del programa (consulte la correspondencia de Curry-Howard ).

Oportunidades redundantes y peligrosas

Bypasses incorporados

El lenguaje contiene herramientas que permiten al programador violar la disciplina de programación dada en un caso particular. Por ejemplo, un modificador constestablece la propiedad de inmutabilidad de estado para un objeto, pero el modificador mutableestá diseñado específicamente para forzar el permiso para cambiar el estado dentro de un objeto const, es decir, violar la restricción de constness. Además, se permite eliminar dinámicamente un atributo constde un objeto constante, convirtiéndolo en un valor L. La presencia de tales características en el lenguaje hace que los intentos de verificar formalmente el código no tengan sentido y el uso de restricciones para la optimización es imposible.

Sustitución de macros no controlada

Las facilidades de sustitución de macro C ( #define) son tan poderosas como peligrosas. Se conservan en C++ a pesar de que, para todas las tareas para las que se proporcionaron en C, C++ proporcionaba recursos más estrictos y especializados: plantillas, sobrecarga de funciones, funciones en línea, espacios de nombres, escritura más avanzada, extensión de la aplicación, el modificador const. , etc. Hay muchas macros potencialmente peligrosas en las bibliotecas estándar heredadas de C [45] . La metaprogramación de plantillas también se combina a veces con el uso de sustitución de macros para proporcionar los llamados. " azúcar sintáctico ".

Problemas de sobrecarga

Los principios de C++ de función y sobrecarga de operadores conducen a una duplicación de código significativa. Originalmente destinado a introducir el llamado " azúcar sintáctico ", la sobrecarga de operadores en C++ fomenta el comportamiento descontrolado de los operadores elementales para diferentes tipos. Esto aumenta drásticamente el riesgo de errores, sobre todo porque es imposible introducir una nueva sintaxis y cambiar la existente (por ejemplo, crear nuevos operadores o cambiar las prioridades o la asociatividad), aunque la sintaxis de los operadores estándar de C ++ es adecuada a la semántica de todo tipo que puede ser necesario introducir en el programa. Algunos problemas son creados por la posibilidad de una fácil sobrecarga de los operadores / , lo que puede generar errores extremadamente insidiosos y difíciles de encontrar. Al mismo tiempo, algunas operaciones intuitivamente esperadas (limpieza de objetos dinámicos en caso de lanzar excepciones) no se realizan en C++, y una parte significativa de funciones y operadores sobrecargados se llaman implícitamente (conversión de tipos, creación de instancias temporales de clases, etc. .). Como resultado, las herramientas originalmente destinadas a hacer que los programas sean más claros y mejorar el desarrollo y la capacidad de mantenimiento se convierten en otra fuente de código innecesariamente complicado y poco confiable. newdelete

Eficiencia computacional

La cantidad resultante de código ejecutable

El uso de plantillas de C++ es polimorfismo paramétrico a nivel de código fuente, pero cuando se traduce, se convierte en polimorfismo ad hoc (es decir, sobrecarga de funciones), lo que conduce a un aumento significativo en la cantidad de código de máquina en comparación con los lenguajes que tienen un verdadero sistema de tipos polimórficos (descendientes de ML ). Para reducir el tamaño del código de máquina, intentan procesar automáticamente el código fuente antes de la etapa de desenrollado de plantillas [46] [47] . Otra solución podría ser la capacidad de exportar plantillas, que se estandarizó en 1998, pero no está disponible en todos los compiladores, ya que es difícil de implementar [48] [49] [opiniones 4] y para importar bibliotecas de plantillas C ++ a idiomas con una semántica de C++ significativamente diferente, seguiría siendo inútil. Los defensores de C++ cuestionan el grado de exceso de código como exagerado [50] , e incluso ignoran el hecho de que en C el polimorfismo paramétrico se traduce directamente, es decir, sin duplicar cuerpos de funciones en absoluto. Al mismo tiempo, los partidarios de C++ creen que el polimorfismo paramétrico en C es peligroso, es decir, más peligroso que la transición de C a C++ (los que se oponen a C++ argumentan lo contrario, véase más arriba).

Potencial de optimización

Debido al sistema de tipo débil y la abundancia de efectos secundarios , se vuelve extremadamente difícil convertir programas de manera equivalente y, por lo tanto, incorporar muchos algoritmos de optimización en el compilador, como la paralelización automática de programas , la eliminación de subexpresiones comunes , λ-lifting, llamadas a procedimientos con paso de continuación , supercompilación , etc. Como resultado, la efectividad real de los programas de C++ está limitada por las habilidades de los programadores y los esfuerzos invertidos en un proyecto en particular, y una implementación "descuidada" puede ser significativamente inferior en eficiencia a "descuidada". ” implementaciones en lenguajes de nivel superior, lo que se confirma mediante pruebas comparativas de lenguajes [34] . Esta es una barrera significativa contra el uso de C++ en la industria de minería de datos .

Gestión eficiente de la memoria

La responsabilidad de una gestión eficaz de la memoria recae sobre los hombros del desarrollador y depende de sus habilidades. Para la gestión automática de la memoria en C ++, los llamados. "punteros inteligentes", la gestión manual de la memoria reduce la eficiencia de los propios programadores (consulte la sección Eficiencia ) . Numerosas implementaciones de recolección de elementos no utilizados , como la inferencia estática de regiones , no son aplicables a los programas C++ (más precisamente, esto requiere la implementación de un nuevo intérprete de lenguaje además del lenguaje C++, que es muy diferente de C++ tanto en la mayoría de las propiedades objetivas y en general ideología) debido a la necesidad de acceso directo a AST .

Eficiencia

La correlación de los factores de desempeño con los costos de desarrollo, así como la disciplina general y la cultura de programación cultivada en la comunidad de programación, son importantes para los clientes que eligen un lenguaje (y, en consecuencia, prefieren este lenguaje de desarrolladores) para la implementación de sus proyectos. así como para personas que comienzan a aprender programación, especialmente con la intención de programar para sus propias necesidades.

Calidad y cultura de la programación

El principio de C++ " de no imponer un" buen "estilo de programación " es contrario al enfoque industrial de la programación, en el que el papel principal lo juega la calidad del software y la posibilidad de mantener el código no solo por parte del autor. , y para los que se prefieren lenguajes que minimicen la influencia del factor humano , es decir, simplemente " imponer un 'buen' estilo de programación ", aunque dichos lenguajes pueden tener un umbral de entrada más alto.

Existe la opinión de que la preferencia por utilizar C++ (con la posibilidad de elegir lenguajes alternativos) caracteriza negativamente las cualidades profesionales de un programador. Específicamente, Linus Torvalds dice que usa las opiniones positivas de los candidatos sobre C++ como criterio de abandono [opiniones 3] :

C++ es un lenguaje terrible. Lo que lo hace aún más horrendo es el hecho de que muchos programadores analfabetos lo usan... Francamente, incluso si no hay razón para elegir C aparte de mantener alejados a los programadores de C++, eso por sí solo sería una buena razón para usar C.
…He llegado a la conclusión de que realmente preferiría echar a cualquiera que prefiera desarrollar un proyecto en C++ que en C, para que esa persona no arruine el proyecto en el que estoy involucrado.

Linus Torvalds , [33] Arreglando un defectuoso

La evolución continua del lenguaje alienta (ya veces obliga) a los programadores a cambiar el código ya depurado una y otra vez; esto no solo aumenta el costo de desarrollo, sino que también conlleva el riesgo de introducir nuevos errores en el código depurado. En particular, aunque la compatibilidad con versiones anteriores de C fue originalmente uno de los principios básicos de C++, desde 1999 C dejó de ser un subconjunto de C++, por lo que el código C depurado ya no se puede usar en un proyecto de C++ sin modificaciones.

Complejidad por sí misma

C++ es definido por sus apologistas como "el más poderoso" precisamente porque está repleto de características peligrosas y mutuamente contradictorias. Según Eric Raymond , esto convierte al propio lenguaje en un terreno de autoafirmación personal de los programadores, convirtiendo el proceso de desarrollo en un fin en sí mismo:

Los programadores suelen ser individuos extravagantes que se enorgullecen de... su capacidad para manejar la complejidad y las abstracciones con destreza. A menudo compiten entre sí, tratando de descubrir quién puede crear "las complejidades más intrincadas y hermosas". ... los rivales creen que deben competir con las "decoraciones" de otras personas agregando las suyas propias. Muy pronto, el "tumor masivo" se convierte en el estándar de la industria, y todo el mundo ejecuta grandes programas con errores que ni siquiera sus creadores pueden satisfacer.

… este enfoque puede causar problemas si los programadores hacen cosas simples de formas complejas, simplemente porque conocen esas formas y saben cómo usarlas.

—Eric Raymond en [51] Sabotaje

Se han notado casos en los que programadores descuidados, utilizando la fuerte dependencia del contexto de C ++ y la falta de capacidad para rastrear definiciones de macro por parte del compilador, ralentizaron el desarrollo del proyecto escribiendo uno o dos adicionales, correctos desde el punto de vista del compilador. de vista, líneas de código, pero introduciendo un error manifestado espontáneamente difícil de detectar a su costa. Por ejemplo:

#define si(a) si(al azar())


#definir ji

En lenguajes con corrección comprobada , incluso con facilidades de macros avanzadas, es imposible hacer daño de esta manera.

Producto poco fiable

Una abundancia irrazonable de efectos secundarios, combinada con la falta de control del sistema de tiempo de ejecución del lenguaje y un sistema de tipo débil, hace que los programas de C++ sean propensos a fallas fatales impredecibles (las conocidas fallas con mensajes como "Violación de acceso", "Función virtual pura call" o "El programa realizó una operación ilegal y se cerrará"), lo que excluye el uso de C ++ con altos requisitos de tolerancia a fallas. Además, aumenta la duración del propio proceso de desarrollo [34] .

Gestión de proyectos

Los factores enumerados anteriormente hacen que la complejidad de la gestión de proyectos de C++ sea una de las más altas en la industria del desarrollo de software.

James Coggins, columnista de The C++ Report durante cuatro años , explica:
 El problema es que los programadores de programación orientada a objetos han estado experimentando con aplicaciones incestuosas y apuntando a un bajo nivel de abstracción. Por ejemplo, crearon clases como "lista enlazada" en lugar de "interfaz de usuario" o "haz de radiación" o "modelo de elementos finitos". Desafortunadamente, la verificación de tipo fuerte, que ayuda a los programadores de C++ a evitar errores, también dificulta la creación de objetos grandes a partir de objetos pequeños.

F. Brooks , El hombre-mes mítico

Influencia y alternativas

El único descendiente directo de C++ es el lenguaje D , destinado a ser una reelaboración de C++ para abordar sus problemas más obvios. Los autores abandonaron la compatibilidad con C, conservando la sintaxis y muchos de los principios básicos de C ++ e introduciendo funciones en el lenguaje que son características de los nuevos lenguajes. D no tiene preprocesador, ni archivos de encabezado, ni herencia múltiple, sino un sistema de módulos, interfaces, arreglos asociativos, soporte para Unicode en cadenas, recolección de elementos no utilizados (manteniendo la posibilidad de administración manual de la memoria), subprocesos múltiples incorporados, inferencia de tipos , declaración explícita de funciones puras y valores inmutables. El uso de D es muy limitado, no puede considerarse un competidor real de C ++.

El competidor más antiguo de C++ en tareas de bajo nivel es Objective-C , también basado en el principio de combinar C con un modelo de objetos, solo el modelo de objetos se hereda de Smalltalk . Objective-C, al igual que su descendiente Swift , se usa ampliamente para el desarrollo de software para macOS e iOS.

Una de las primeras alternativas a C++ en la programación de aplicaciones fue el lenguaje Java . A menudo se considera erróneamente un descendiente directo de C++; de hecho, la semántica de Java se hereda del lenguaje Modula-2 y la semántica básica de C++ no se puede rastrear en Java. Dado esto, y la genealogía de los lenguajes (Modula-2 es un descendiente de Simula , como C++, pero no es C), Java es más correctamente llamado el " primo segundo " de C++, en lugar del " heredero ". Lo mismo puede decirse del lenguaje C# , aunque el porcentaje de afinidad con C++ es ligeramente superior al de Java.

Un intento de combinar la seguridad y la velocidad de desarrollo de Java y C# con las capacidades de C++ fue el dialecto de C++ administrado (posteriormente C++/CLI ). Fue desarrollado por Microsoft principalmente para trasladar proyectos C++ existentes a la plataforma Microsoft .NET. Los programas se ejecutan bajo CLR y pueden usar la matriz completa de bibliotecas .NET, pero hay una serie de restricciones en el uso de funciones de C++, lo que reduce efectivamente C++ a C#. Este dialecto no ha recibido un amplio reconocimiento y se utiliza principalmente para vincular bibliotecas escritas en C ++ puro con aplicaciones C #.

Una forma alternativa de desarrollar el lenguaje C es combinarlo no con la programación orientada a objetos, sino con la programación aplicativa , es decir, mejorando la abstracción, el rigor y la modularidad de los programas de bajo nivel proporcionando un comportamiento predecible y transparencia referencial . Ejemplos de trabajo en esta línea son los lenguajes BitC , Cyclone y Limbo . Aunque también hay intentos exitosos de usar FP en problemas en tiempo real sin integración con herramientas C [52] [53] [54] , todavía en este momento (2013) en desarrollo de bajo nivel, el uso de herramientas C hasta cierto punto tiene una mejor relación entre la intensidad del trabajo y la eficiencia. Los desarrolladores de Python y Lua han puesto mucho esfuerzo en Python y Lua para garantizar que los programadores de C++ utilicen estos lenguajes, por lo que de todos los lenguajes que están estrechamente relacionados con FP, son los que se utilizan con mayor frecuencia. Se señaló que se usa junto con C ++ en el mismo proyecto. Los puntos de contacto más significativos entre C++ y FP son los enlaces de bibliotecas wxWidgets y Qt desarrollados en C++ con una ideología específica de C++ a Lisp , Haskell y Python (en la mayoría de los casos, los enlaces a lenguajes funcionales se realizan para bibliotecas escritas en C u otros lenguajes funcionales).

Otro lenguaje considerado competidor de C++ es Nemerle , que es el resultado de un intento de combinar el modelo de escritura Hindley-Milner y un subconjunto de macros de Common Lisp con C# [55] . En la misma línea está F# de Microsoft  , un dialecto de ML adaptado para el entorno .NET.

Un intento de crear un reemplazo industrial para C / C ++ fue el lenguaje de programación Go desarrollado por Google en 2009 . Los autores del lenguaje señalan directamente que el motivo de su creación fueron las deficiencias del proceso de desarrollo provocadas por las peculiaridades de los lenguajes C y C++ [56] . Go es un lenguaje imperativo compacto y sin complicaciones con sintaxis similar a C, sin preprocesador, escritura estática, escritura fuerte, sistema de empaquetado, administración automática de memoria, algunas características funcionales, subsistema OOP construido económicamente sin soporte para herencia de implementación, pero con interfaces y escritura pato , subprocesos múltiples incorporados basados ​​en corrutinas y tuberías (a-la Occam ). El lenguaje se posiciona como una alternativa a C ++, es decir, ante todo, un medio para el desarrollo grupal de sistemas informáticos altamente complejos, incluidos los distribuidos, que permiten, si es necesario, una programación de bajo nivel.

En el mismo nicho ecológico con C/C++ está Rust, desarrollado en 2010 y mantenido por Mozilla Corporation , centrado en la gestión segura de la memoria sin el uso de un recolector de basura . En particular, los planes para reemplazar parcialmente C / C ++ con Rust fueron anunciados en 2019 por Microsoft [57] .

Véase también

Notas

  1. ISO/IEC 14882:2020 Lenguajes de programación - C++ - 2020.
  2. Gubina G. G. Inglés informático. Parte I. Inglés Informático. Parte I. Tutorial . — P. 385. Archivado el 3 de diciembre de 2017 en Wayback Machine .
  3. Preguntas frecuentes de Bjarne Stroustrup  . Bjarne Stroustrup (1 de octubre de 2017). - "El nombre C++ (pronunciado "ver más más")". Fecha de acceso: 4 de diciembre de 2017. Archivado desde el original el 6 de febrero de 2016.
  4. Schildt, 1998 .
  5. 1 2 Stroustrup, 1999 , 2.1. ¿Qué es C++?, pág. 57.
  6. Stanley Lippman, Pure C++: Hello, C++/CLI Archivado el 6 de junio de 2011 en Wayback Machine . 
  7. 1 2 Stroustrup, 1999 , 1.4. Observaciones históricas, pág. 46.
  8. C++-Estándares . Consultado el 14 de noviembre de 2010. Archivado desde el original el 20 de noviembre de 2010.
  9. Bjarne Stroustrup. Glosario de C++ (enlace no disponible) . Consultado el 8 de junio de 2007. Archivado desde el original el 1 de mayo de 2011. 
  10. ¿Dónde encuentro los documentos estándar actuales de C o C++? http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents Archivado el 29 de noviembre de 2015 en Wayback Machine .
  11. Consulte una lista en http://en.cppreference.com/w/cpp/experimental . Archivado el 18 de noviembre de 2015 en Wayback Machine . Visitado el 5 de enero de 2015.
  12. Yandex organiza un grupo de trabajo para estandarizar el lenguaje C++ . Medios ICS. Consultado el 29 de agosto de 2018. Archivado desde el original el 29 de agosto de 2018.
  13. Stroustrup, El diseño y la evolución de C++, 2007 .
  14. ISO/IEC 14882:1998, sección 6.4, cláusula 4: "El valor de una condición que es una declaración inicializada en una declaración que no sea una switchdeclaración es el valor de la variable declarada convertida implícitamente en bool... El valor de una condición es decir, una expresión es el valor de la expresión, implícitamente convertido a booldeclaraciones for distintas a switch; si esa conversión está mal formada, el programa está mal formado".
  15. STLport: ¡Bienvenido! . Consultado el 26 de julio de 2007. Archivado desde el original el 7 de junio de 2018.
  16. Stroustrup, 1999 , 1.6.
  17. std::vector-cppreference.com . Fecha de acceso: 28 de noviembre de 2015. Archivado desde el original el 27 de noviembre de 2015.
  18. std::realloc-cppreference.com . Fecha de acceso: 28 de noviembre de 2015. Archivado desde el original el 4 de diciembre de 2015.
  19. Entrevista de B. Stroustrup con LinuxWorld.com . Consultado el 4 de enero de 2013. Archivado desde el original el 27 de enero de 2013.
  20. Entrevista de B. Stroustrup con la revista System Administrator . Fecha de acceso: 4 de enero de 2013. Archivado desde el original el 9 de febrero de 2013.
  21. CNews: Entrevista exclusiva con el creador del lenguaje de programación C++ (enlace no disponible) . Consultado el 1 de noviembre de 2019. Archivado desde el original el 17 de marzo de 2015. 
  22. 1 2 3 4 Un experimento en la productividad de creación de prototipos de software. Paul Hudak, Mark P. Jones. Universidad de Yale, Departamento de Ciencias de la Computación, New Haven, CT 06518. 4 de julio de 1994.
  23. K. Czarnecki, J. O'Donnell, J. Striegnitz, W. Taha. Implementación de DSL en metaocaml, plantilla haskell y C++ . — Universidad de Waterloo, Universidad de Glasgow, Centro de Investigación Julich, Universidad de Rice, 2004. Archivado desde el original el 7 de abril de 2022. .
    Cita: La metaprogramación de plantillas de C++ adolece de una serie de limitaciones, incluidos problemas de portabilidad debido a las limitaciones del compilador (aunque esto ha mejorado significativamente en los últimos años), falta de soporte de depuración o IO durante la creación de instancias de plantillas, largos tiempos de compilación, errores largos e incomprensibles , mala legibilidad del código y pobre informe de errores.
  24. 1 2 3 Lutz Prechelt ( Universität Karlsruhe ). Una comparación empírica de C, C++, Java, Perl, Python, Rexx y Tcl para un programa de búsqueda/procesamiento de cadenas  ( pdf) Freie Universität Berlin (14 de marzo de 2000). Consultado el 20 de noviembre de 2019. Archivado desde el original el 3 de enero de 2020.
  25. Ada, C, C++ y Java vs. The Steelman" David A. Wheeler julio/agosto de 1997 (enlace no disponible) . Consultado el 23 de marzo de 2019. Archivado desde el original el 23 de marzo de 2019. 
  26. 1 2 "Una comparación de lenguajes de programación comunes utilizados en bioinformática" . Consultado el 2 de septiembre de 2021. Archivado desde el original el 2 de septiembre de 2021.
  27. Comparación de lenguajes de programación en la implementación de algoritmos bioinformáticos - descripción del experimento. . Consultado el 2 de septiembre de 2021. Archivado desde el original el 2 de septiembre de 2021.
  28. Comparación de las características de Ada y C++ (en) . Consultado el 23 de marzo de 2019. Archivado desde el original el 23 de marzo de 2019.
  29. Stephen Zeigler, Comparación de los costos de desarrollo de C y Ada. Archivado desde el original el 4 de abril de 2007.
  30. 1.2 Objetivos de diseño del lenguaje de programación Java™ .  El entorno del lenguaje Java . Oráculo (1 de enero de 1999) . Consultado el 14 de enero de 2013. Archivado desde el original el 23 de enero de 2013.
  31. Guía de estilo de Google C++. Excepciones. . Consultado el 31 de marzo de 2019. Archivado desde el original el 16 de marzo de 2019.
  32. Boehm H. Ventajas y desventajas de la recolección de basura conservadora . Archivado desde el original el 24 de julio de 2013.
    (enlace de Raymond, Eric . The Art of Unix Programming. - 2005. - p. 357. - 544 p. - ISBN 5-8459-0791-8 . )
  33. 1 2 3 4 Correspondencia abierta gmane.comp.version-control.git con fecha 06/09/2007 (enlace inaccesible) . Consultado el 5 de agosto de 2013. Archivado desde el original el 9 de diciembre de 2013. 
  34. 1 2 3 Ray Tracer Language Comparison (referencia de lenguajes de programación - ffconsultancy.com/languages/ray_tracer/)
  35. 12 Martín Ward . Programación Orientada al Lenguaje . - Departamento de Ciencias de la Computación, Laboratorios de Ciencias, 1994. Archivado desde el original el 4 de marzo de 2016.
  36. Paul Hudak. Herramientas y lenguajes específicos de dominio modular. — Departamento de Ciencias de la Computación, Universidad de Yale.
  37. Definición de programación orientada a objetos de Alan Kay (enlace no disponible) . Fecha de acceso: 5 de agosto de 2013. Archivado desde el original el 24 de agosto de 2013. 
  38. Schildt, Teoría y práctica de C++, 1996 , p. 64-67.
  39. 12 Ian Joyner . Una crítica de C++ y las tendencias de programación y lenguaje de la década de 1990 - 3.ª edición . - derechos de autor y lista de publicaciones . Archivado desde el original el 25 de noviembre de 2013.
  40. Paulson, Lawrence C. ML para el programador de trabajo, segunda edición. - Universidad de Cambridge: Cambridge University Press, 1996. - ISBN 0-521-57050-6 (tapa dura), 0-521-56543-X (tapa blanda). , c.271-285
  41. Walid Taha. Idiomas específicos de dominio . — Departamento de Ciencias de la Computación, Universidad Rice. Archivado desde el original el 24 de octubre de 2013.
  42. Lugovsky VS Uso de una jerarquía de lenguajes específicos de dominio en el diseño de sistemas de software complejos . - 2008. Archivado el 10 de agosto de 2016.
  43. Andréi Karpov. 20 trampas de portar código C++ a una plataforma de 64 bits . - Revista RSDN #1-2007, 2007. Archivado desde el original el 2 de abril de 2015.
  44. Don Clugston, CSG Solar Pty Ltd (traducido por Denis Bulichenko). Punteros de funciones miembro y la implementación más rápida de delegados en C++ . — Revista RSDN #6-2004. Archivado desde el original el 19 de octubre de 2013.
  45. Stroustrup, Programación: Principios y práctica de C++, 2001
  46. Dave Gotner. Plantillas sin código hinchado . — Dra . Dobb's Journal , enero de 1995. Archivado desde el original el 7 de junio de 2008.
  47. Adrián Stone. Minimización de la sobrecarga de código: creación de instancias de plantillas redundantes (enlace descendente) . Game Angst (22 de septiembre de 2009). Fecha de acceso: 19 de enero de 2010. Archivado desde el original el 8 de diciembre de 2011. 
  48. Sutter de hierbas . Resumen de conformidad de C++ . — Dra . Dobb's Journal , enero de 2001. Archivado desde el original el 15 de enero de 2009.
  49. ¿Existen compiladores que implementen todo esto? (enlace no disponible) . comp.std.c++ preguntas frecuentes / El lenguaje C++ . Comeau Computing (10 de diciembre de 2008). Fecha de acceso: 19 de enero de 2010. Archivado desde el original el 30 de abril de 2009. 
  50. Scott Meyers . Inflación de código debido a las plantillas . comp.lang.c++.moderado . Usenet (16 de mayo de 2002). Recuperado: 19 de enero de 2010.
  51. Eric Raymond . Arte de programar para Unix = El Arte de Unix. - Williams, 2005. - ISBN 5-8459-0791-8 .
  52. Zhanyong Wan y Paul Hudak. FRP basado en eventos  // Departamento de Ciencias de la Computación, Universidad de Yale. Archivado desde el original el 16 de agosto de 2011.
  53. Walid Taha  (inglés)  (enlace no disponible) . Escuela de Ingeniería Universidad Rice . Consultado el 20 de noviembre de 2019. Archivado desde el original el 13 de agosto de 2013.
  54. MLKit (enlace descendente) . Consultado el 30 de julio de 2013. Archivado desde el original el 17 de septiembre de 2013. 
  55. Chistyakov Vlad alias VladD2. Azúcar sintáctico o C++ vs. Nemerle :)  // Revista RSDN #1-2006. - 24/05/2006. Archivado desde el original el 13 de diciembre de 2013.
  56. Ir a Google: Diseño de lenguaje al servicio de la ingeniería de software . talks.golang.org. Consultado el 19 de septiembre de 2017. Archivado desde el original el 25 de enero de 2021.
  57. Catalín Cimpanu. Microsoft para explorar el uso de Rust  . ZDNet (17 de junio de 2019). Consultado el 26 de septiembre de 2019. Archivado desde el original el 15 de octubre de 2019.
Opiniones
  1. Popularidad del lenguaje de programación (enlace inaccesible) (2009). Fecha de acceso: 16 de enero de 2009. Archivado desde el original el 16 de enero de 2009. 
  2. Índice de la comunidad de programación de TIOBE (enlace no disponible) (2009). Consultado el 6 de mayo de 2009. Archivado desde el original el 4 de mayo de 2009. 
  3. 1 2 Correspondencia abierta gmane.comp.version-control.git con fecha 06/09/2007 (enlace inaccesible) . Consultado el 5 de agosto de 2013. Archivado desde el original el 9 de diciembre de 2013. 
  4. van Dooren. Palabra clave del día en C++: exportar (enlace no disponible) . Blogs@MSMVPs (24 de septiembre de 2008). “La palabra clave export es un poco como el bosón de Higgs de C++. Teóricamente existe, está descrito por el estándar y nadie lo ha visto en la naturaleza. … Hay 1 front-end de compilador de C++ en el mundo que realmente lo admite”. Fecha de acceso: 19 de enero de 2010. Archivado desde el original el 6 de mayo de 2009. 
Explicaciones
  1. Por ejemplo, Boost.Lambdase comercializa como una función lambda, pero C++ no implementa el cálculo lambda de Church en su totalidad; la imitación de combinadores a través de un lenguaje de plantilla es demasiado difícil para esperar su uso en la práctica; las continuaciones heredadas de C se consideran no ideomáticas y peligrosas, y su implementación a través del lenguaje de plantilla es imposible; además, no es posible usar λ-lifting para optimizar C++, por lo que en realidad es Boost.Lambda solo una función anónima, no un objeto del cálculo lambda.

Literatura

  • Bjorn Stroustrup . Lenguaje de programación C++ = El lenguaje de programación C++ / Per. De inglés. - 3ra ed. - San Petersburgo. ; M .: Dialecto de Nevsky - Binom , 1999. - 991 p. - 3000 copias.  — ISBN 5-7940-0031-7 (dialecto de Nevsky), ISBN 5-7989-0127-0 (Binom), ISBN 0-201-88954-4 (inglés).
  • Bjorn Stroustrup . Lenguaje de programación C++. Edición especial = El lenguaje de programación C++. edición especial. - M. : Binom-Press, 2007. - 1104 p. — ISBN 5-7989-0223-4 .
  • Bjorn Stroustrup . Programación: principios y práctica con C++, edición revisada = Programación: principios y práctica con C++. — M .: Williams , 2011. — S. 1248. — ISBN 978-5-8459-1705-8 .
  • Bjorn Stroustrup . Diseño y Evolución de C++ = El Diseño y Evolución de C++. - San Petersburgo. : Pedro, 2007. - 445 p. — ISBN 5-469-01217-4 .
  • Bjorn Stroustrup . Lenguaje de programación C++. Curso corto. - 2019. - 320 págs. - ISBN 978-5-907144-12-5 .
  • Bjorn Stroustrup . Programación: principios y práctica usando C++. - 2016. - 1328 págs. - ISBN 978-5-8459-1949-6 .
  • Siddhartha Rao. Enséñese a sí mismo C++ en una hora al día, 7.ª edición (C++11) = Sams Enséñese a sí mismo C++ en una hora al día, 7.ª edición. - M. : "Williams" , 2013. - 688 p. — ISBN 978-5-8459-1825-3 .
  • Stephens DR C++. Colección de recetas. - KUDITS-PRESS, 2007. - 624 p. - ISBN 5-91136-030-6 .
  • Esteban Prata. Lenguaje de programación C++ (C++11). Clases y ejercicios = C++ Primer Plus, 6.ª edición (Biblioteca para desarrolladores). - 6ª ed. — M. : Williams , 2012. — 1248 p. - ISBN 978-5-8459-1778-2 .
  • Esteban Prata. Lenguaje de programación C. Lecciones y ejercicios. — M. : Williams , 2015. — 928 p. - ISBN 978-5-8459-1950-2 .
  • Ivor Horton. Visual C ++ 2010: curso completo = Principios de Visual C ++ de Ivor Horton 2010. - M . : Dialéctica , 2010. - S. 1216. - ISBN 978-5-8459-1698-3 .
  • Herbert Schildt . La Referencia Completa a C++ = C++: La Referencia Completa. - 4ª ed. - M .: Williams , 2011. - S. 800. - ISBN 978-5-8459-0489-8 .
  • Herbert Schildt . Teoría y práctica de C++ = Experto C++ de Schildt. - San Petersburgo. : BHV - San Petersburgo, 1996. - ISBN 0-07-882209-2 , 5-7791-0029-2.
  • PJ Plauger. Juegos de adivinanzas de lenguajes de programación - Si C++ es la respuesta, ¿cuál es la pregunta? // Dra. Diario de Dobb . - Octubre de 1993.
  • El manual de Unix-Haters  (indefinido) . - Grupo Internacional de Datos , 1994.
  • Ian Joyner. Una crítica de C++ y las tendencias de programación y lenguaje de la década de 1990 - 3.ª edición  // derechos de autor y lista de publicaciones . — 1996.
  • Scott Meyers. C++ moderno efectivo: 42 recomendaciones para usar C++ 11 y C++ 14 = C++ moderno efectivo: 42 formas específicas de mejorar el uso de C++ 11 y C++ 14 / Per. De inglés. - Williams, 2016. - 304 págs. - ISBN 978-5-8459-2000-3 .
  • Herbert Schildt . C++ La referencia completa Tercera edición. - Osborne McGraw-Hill, 1998. - ISBN 978-0-07-882476-0 .
  • Jeremy A. Hansen La guía de Rook para C ++ (un libro de texto con licencia Creative Commons) .

Enlaces

  • isocpp.org (  inglés) - sitio web oficial de C++