C++ 11 y su nuevo estilo, explicado por Bjarne Stroustrup

En una serie de charlas muy interesantes del evento GoingNative2012 organizado por Microsoft, el mísmisimo creador de C++, Bjarne Stroustrup, dio una charla sobre el nuevo estilo de programación introducido por el nuevo estándar C++ 11.

El tema de la charla no son las nuevas funcionalidades del lenguaje, sino cómo usarlas correctamente; eso es lo que Bjarne denomina "estilo". A continuación, un resumen de los puntos esenciales:

  • Type-rich interfaces: Se puede usar sufijos para indicar unidades, por ejemplo (ver la nueva keyword constexpr).
  • Usar RAII para recursos: memoria, archivos, sockets, hardware, recursos del sistema operativo (threads, mutexes, semáforos, etc).
  • Evitar el uso de punteros, especialmente en interfaces (mantener esos usos acotados a implementaciones de funciones). Usar smart pointers como unique_ptr y shared_ptr. No usar este último si no se está compartiendo el recurso. Y antes de considerar usar punteros, considerar usar referencias, o aún mejor, crear los objetos en stack. Todo esto cuando hablamos de usar punteros para expresar la pertenencia de un recurso. Si sólo queremos apuntar a un objeto que no es nuestro y no podemos usar una referencia, usar un puntero es aceptable.
  • Evitar arrays nativos; usar contenedores STL. Si es necesario pasar un array nativo a una API de terceros, por ejemplo, se puede usar un std::vector, que garantiza que toda la memoria sea contigua, igual que en un array nativo. A la función de la API se le pasa &v[0], donde v es el std::vector.
  • Cuando tenemos objetos grandes (por ejemplo, una clase Matrix que usamos para matrices de 10000 x 10000), y queremos hacer una función que devuelva una instancia de esa clase (un operator+, por ejemplo), tenemos el problema de que creamos una matriz local y devolvemos una copia. Es mucho overhead; una nueva funcionalidad clave de C++ 11 son las "move semantics". En vez de copiar, "muevo". En el ejemplo dado, devolvemos una Matrix por valor e implementamos un "move constructor", que define cómo se hace el "move". Más detalles sobre esto en un post futuro. Baste con aclarar que todos los contenedores de la STL implementan esto (excepto std::array), con lo cual la performance sube sólo por compilar para C++11 si ya usábamos contenedores STL.
  • Usar siempre que sea posible.
  • El código de bajo nivel no siempre es más eficiente (por ej: el sort de C es más lento que el qsort de C++). Siempre medir ante la duda y evitar micro-optimizaciones prematuras. Bajo nivel implica escribir más código, lo cual implica mayor posibilidad de bugs y mayor costo de mantenimiento.
  • C++ 11 ofrece clases para manejo de concurrencia: std::thread y std::mutex, entre ellas. Incluso mejor, std::async permite decidir al runtime si usar otro thread o no, dejándole toda la complejidad del manejo de la concurrencia.
  • También se agrega soporte para expresiones lambda.

Por último, acá hay un cuadro con qué funcionalidades de C++ 11 implementa cada compilador (MSVC = Visual Studio).

Comments

Popular posts from this blog

VB.NET: Raise base class events from a derived class

Apache Kafka - I - High level architecture and concepts

Upgrading Lodash from 3.x to 4.x