Novedades en C++



Lisardo Fernández Cordeiro
ETSE   –  2º GII  –  EDA
Universidad de Valencia

  
      La incesante actividad del hombre y su obcecado programa genético, incapaz de conformarse con lo que se le presente por delante, lo sitúan en la eterna paradoja magistralmente descrita por Mario Benedetti  “cuando creíamos que teníamos todas las respuestas, de pronto, cambiaron todas las preguntas”.
      Resulta una obviedad pensar en la lógica evolución de la ciencia y la perenne adecuación a los nuevos conocimientos que precisan los sistemas involucrados en ella, en un ciclo infinito. La destreza de los sacrificados programadores se reconduce, necesariamente, a la implementación de algoritmos que resuelvan necesidades específicas sobre aplicaciones concretas, sin dedicar líneas de código ni preocupaciones dolorosas, a estructuras engorrosas, detalles declarativos o costosas descripciones de instrucciones simples.
      Con este propósito se levantó un buen día un optimista comité de desarrollo para dar a luz, tras muchos almuerzos aplazados, un estándar la mar de apañao, capaz de ayudar al desarrollo de aplicaciones poderosas con menor esfuerzo. Más de un programador sentirá alivio y los más, renovadas energías para seguir evolucionando la manera de decir a un cacharro tonto como realizar proezas que parezcan inteligentes.
      Debajo de los centenares de referencias que se pueden encontrar en una búsqueda simple con el navegador preferido del lector, se encuentra una gran sopa de mejoras que, a poco que a uno se le despiste el vistazo, se pierde la esencia de las bondades. De modo que organizaremos el trabajo en los grandes bloques que lo sabios de Wikipedia han tenido a bien establecer.


rendimiento
      La adecuada gestión de memoria RAM disponible en una máquina es fundamental para que un usuario no caiga víctima del sueño, a la espera de ejecución de una orden. Cualquier iniciado en estos lares conoce su importancia y la incidencia directa en la velocidad de cómputo que puede ofrecer un mismo ordenador, en función de la eficiencia del lenguaje a la hora de manejar variables, constantes y sus pasos entre funciones.
      El nuevo estándar que nos entretiene en este trabajo, ha modificado el modo de gestionar ciertos valores, expresiones y estructuras, a fin de optimizar el uso que hasta ahora se hacía de la memoria en muchos de los procesos donde se veían involucradas.
      Así, para los rvalues –esos valores que se sitúan a la derecha de las expresiones de asignación- crea referencias a través de su paso a funciones, que no precisan de los devoradores replicantes de valor, cuando precisamos de niveles de profundidad elevados, con punteros a memoria temporal adecuados para cada valor, que posibilita su cambio –los rvalues, por principio, son constantes- gracias a un novedoso concepto de “semántica móvil”.
      También en el terreno de las expresiones constantes que pasan a formar parte de confusas expresiones para su manejo como operadores o argumentos al estilo de variables, se procura un prefijo “constexpr” que aclara su alcance en este área, facilitando la escritura de código y su gestión ejecutiva.
      El uso de plantillas también se ha revisado, de tal modo que se facilita la asignación de plantillas concretasen distintos puntos del código con “extern template”, informando al compilador que no se instancien, sino que se establezcan referencias externas, con el fin de optimizar el tiempo de compilación y el código generado.
      En definitiva, encontramos una profunda revisión de conceptos responsables del servicio organizativo de memoria y los procesos de compilación de programas, orientada a la eficiencia, redundando en un rendimiento mayor.
usabilidad
      Es primordial que el aprendiz de brujo e incluso el brujo mismo, manejen un lenguaje sencillo, fácil due implementar, robusto, que ahorre líneas de código repetido, maneje con seguridad los tipos y que los errores en la programación sean menores.
      Con este objetivo, se han pulido e implementado características nuevas, muchas de ellas importadas de otros lenguajes, que facilitan la elaboración de aplicaciones. Lógicamente, por razones de espacio, no se podrán ver todas en esta sencilla aproximación al nuevo estándar, si bien las más resultonas bien se merecen una mención específica.
      Una de estas novedades importantes se refiere a la inicialización de listas, con una expresión tal que “inizialicer_list<Tipo> nombre”. Con ella en un constructor de clase o incluso en una función, se puede pasar por argumento una lista de valores con que se pretenda inicializar un objeto o con los que proceda una función.
      Uno de los quebraderos de cabeza más importantes a la hora de programar es la necesidad de mantener el tipo de las variables, funciones y expresiones que se manejan a lo largo de todo el código, de tal manera que puede resultar difícil de seguir e inducir a multitud de errores de forma y no de fondo, ralentizando la generación e código. Por ello se ha recuperado una palabra reservada “auto” dándole una utilidad diferente ala inicial de almacenamiento automático que provenía de C. En esta revisión, tiene la valiosa función de deducir y asignar un Tipo a las variables que le siguen o al retorno en la declaración de una función.
      En la parte del compilador, para facilitarle también la labor en la asignación de tipo, y teniendo en cuenta que “auto” solo sirve en la declaración de la variable, se diseña la palabra reservada “decltype” para poder usarse en cualquier momento en el que se deba asegurar o resulte complejo el conocimiento del tipo de la variable o retorno de función que se maneje, asignando el tipo correcto a la variable que antecede.
      Una de las facilidades más sobresalientes es, sin duda, el bucle “for” basado en rango. Ya no será necesario declarar un engorroso interator o la larguísima línea de comandos propia del bucle conocido por todos. Los casos en os que haya que recorrer una lista… muchos, será suficiente definir la variable de recorrido con su tipo y determinar la lista sobre la que actuará. Fantástico.
      Y no menos sobresaliente es la inclusión de las expresiones lambda, que permiten definir funciones localmente, justo en el sitio donde se van a utilizar. También llamadas funciones anónimas al prescindir de la declaración inicial, reducen código y riesgo de equívocos con las declaraciones de tipo.
      Los constructores de objetos de clase estaban muy restringidos en sus ámbitos de actuación, no pudiendo heredarse ni llamarse entre sí. Sin embargo, en el nuevo estándar esto ya es posible. Los objetos de una clase podrán construirse a partir de otros constructores de la misma clase o incluso de constructores de clases padre.
      Otro de los quebraderos de cabeza que se resuelven, es la eterna dicotomía de 0 como valor de puntero nulo NULL o como valor entero. Para que no se realicen conversiones de tipo incorrectas que devenguen en errores de tipo, se introduce “nullptr” para los caso de puntero nulo, sin influencia en el tipo que devuelve.
      En ocasiones, cuando se ha tenido que definir un vector de listas o de vectores de la STL, nos hemos topado con la necesaria precaución de separa los símbolos de cierre de declaración con un espacio para evitar errores con el operador>>. C++11 resuelve este problema para no tener que estar pendientes de los eternos formalismos tan reñidos con la eficiencia en al escritura de código.
funcionalidad
      La implementación de una serie de características capaces de fortalecer el lenguaje con capacidades no existentes, de tediosa programación, o incluso vinculadas a librerías de complejo transporte, limitando las capacidades multiplataforma, han creado una inmensa satisfacción para los desarrolladores vinculados a este lenguaje.
      Características de funcionalidad importantes integran los literales “string”, con capacidad para trabajar con Unicode, definiendo la cadena correctamente con un prefijo adecuado al tipo de cadena que se pretenda utilizar. Adicionalmente, con el propósito de poder incluir dentro de las cadenas caracteres especiales que funcionarían como secuencias de escape, se introduce el prefijo “R” acompañado o no de “delimiter” para otorgar carácter de parte de la cadena a los especiales.
      Otras de las novedades más importantes es la gestión de memoria y variables en la  programación multi-hilo. No resulta sencillo gestionar el espacio de memoria y la localidad o globalidad de las variables cuando diferentes hilos de programa pretenden hacer uso de localizaciones iguales o accesos a variables por parte de varios hilos. Se deben establecer los cauces adecuados de construcción y destrucción de variables para cada hilo, así como dotar de privacidad o no a ciertas variables.
      Sinceramente, conforme uno va profundizando en las mejoras del lenguaje, más se da cuenta de lo mucho que le faltaba por saber de C++, sus bondades y limitaciones inteligentemente resueltas en esta profunda revisión. Un ejemplo de ello es la declaración de funciones con métodos por defecto de creación automática con la expresión “defaulted”. Es más, si de todos los métodos creados por defecto, se pretende la limitación de alguno de ellos, nada más sencillo que asignar a la definición del método la expresión “deleted”.
      En el terreno del control de errores del programa a través de asertos, vistos y frecuentemente utilizados en la depuración de aplicaciones en C++, tanto en tiempo de ejecución con “assert”, como en tiempo de compilación con “#error”, existían problemas en la detección de errores cuando intervenían templates en el código. La solución planteada a este inconveniente es a través de la funcionalidad de “static_assert”.
librerías
      Como no podía ser de otra manera, todo lo anteriormente descrito tiene que ver con las librerías, su remodelación, actualización e integración en el nuevo lenguaje.
      Una de las características sobresalientes de la revisión que nos ocupa, es la integración en la librería estándar de la clase “thread”. La gestión multi-hilo referenciada anteriormente, se carga con una potencia y una flexibilidad de gran contenido. La eficiencia a bajo nivel de estas estructuras se complementa con la flexibilidad de estructuración del funcionamiento e interdependencia de los diferentes hilos de programa y los modelos de trabajo en función de las asignaciones de memoria y expectativas de acceso a variables. Vale la pena dedicarle tiempo a este aspecto de gran potencialidad para el aprovechamiento de los potentes procesadores multinúcleo.
      Es digno de mención el funcionamiento de la tuplas u objetos que albergan diferentes tipos de variables, con ágil y flexible grado de interacción y aprovechamiento de los recursos que brinda la posibilidad de contener un almacén heterogéneo de tipos.
      Para los que han tenido la oportunidad de conocer las bondades del almacenamiento de datos monotipados u objetos en estructuras de árbol a través de las facilidades de “map” u otras similares, seguro habrán echado en falta el alto rendimiento de las tablas hash –tablas desordenadas-. Se ofrecen cuatro tipos diferentes de tablas hash en función de si aceptan o no duplicado de claves y si mapean o no las claves a valores asociados.
      Las dificultades que ha representado el trabajo con los eficientes punteros se regula y minimiza con la adopción de punteros inteligentes, capaces de gestionar la memoria y los límites de trabajo.
      Interesante resulta ver que la función de generación pseudoaleatoria de números también ha sido revisada con la inclusión de trs algoritmos generadores diferentes con particularidades propias, adecuadas a diferentes necesidades.
      Pero no es todo, existen sustanciales mejoras y aportaciones en el terreno de los encapsulamientos referenciados a parámetros y no a copias dentro de funciones, encapsulamientos polimórficos para objetos de funciones, tratamiento de tipo sen metaprogramación, que viene a ser algo así como la posibilidad de un progrma de modificar las características de otro en función de unos parámetros, computación uniforme de tipos de retorno de objetos de funciones y un largo etcétera la mar de interesante.
¡ah! pero si hay más
      A poco que uno se haya introducido en la lectura de este trabajo, habrá comprobado la variopinta cantidad de modificaciones que se han procurado tanto para el núcleo como las librerías del C++ que todos conocíamos.
      Sin embargo, se han quedado pendientes algunas funcionalidades que, conociendo otros lenguajes, se podrían echar de menos.
      Así, el famoso recolector de basura de lenguajes como Java o Python sigue en estudio y mejora para que no represente un problema de rendimiento en la ejecución de aplicaciones en tiempo real, donde el tiempo que precisa la limpieza y reorganización de la memoria cada vez que se llena, puede resultar crítico.
      En el mismo cajón se ha quedado la reflexión o cómo preservar la estructura de alto nivel de la aplicación en el código generado tras la compilación. Perooptimizar estas funcionalidades para que el rendimiento del sistema no se resienta, semeja empresa de enjundia.
      Pero no desesperemos y veamos esta modificación como un nuevo lenguaje donde el soporte para ejecución multihilo, la programación genérica –más centrada en los algoritmos que en los datos-, la compatibilidad con el anterior estándar ampliando sus librerías con nuevas funcionalidades, el incremento en la seguridad de trabajo con tipos, el mayor rendimiento y facilidad para trabajar a bajo nivel con el hardware y la supuesta suavidad en la curva de aprendizaje para aquellos valerosos aventureros del software, posicionan al nuevo lenguaje directamente en los umbrales del futuro que comienza a cada paso.  
conclusión
      Siempre, las palabras de los sabios han servido de inspiración y guía en los albores de cualquier actividad. Así, nada mejor para concluir que las del poeta renacentista alemán Georg Friedrich Philipp Freiherr von Hardenberg, más conocido por el sobrenombre de Novalis:
Lo que ahora no alcanza la perfección, la alcanzará en un intento posterior o reiterado; nada de lo que abrazó la historia es pasajero, y a través de transformaciones innumerables renace de nuevo en formas siempre más ricas.”
dotando de musicalidad poética las de Bjarne Stroustrup, padre de C++, al aseverar la radical novedad que representa el reciente estándar.
bibliografía y/o webferencias
..http://www.softwarequalityconnection.com/2011/06/the-biggest-changes-in-c11-and-why-you-should-care/
..http://es.wikipedia.org/wiki/C%2B%2B11
..http://jdgarcia-vision.blogspot.com/2011/09/una-nueva-vida-para-auto-en-c11.html
..http://jdgarcia-vision.blogspot.com/search/label/c%2B%2B11

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *