Acerca del puntero implícito this

Puntero this


Última actualización del post: Diciembre de 2019

En C++, todo proceso llevado a cabo por una función miembro no-estática de una clase se realiza implícitamente sobre el objeto *this, siendo this el nombre del puntero que almacena la dirección en memoria del objeto que invocó a dicha función.

El tipo del puntero this será cv X*, siendo X el nombre de la clase a la que pertenezca la función miembro y cv los calificadores const-volatile que dicha función pudiese tener. Observemos, a este respecto, que los constructores y destructores no pueden acompañarse de dichos calificadores, por lo que el puntero this siempre será de tipo X* en su interior.

El puntero this puede ser empleado en el cuerpo de cualquier función miembro no-estática, en la lista de inicialización de un constructor y en los inicializadores por defecto de datos miembro. La indirección this-> es añadida implícitamente al comienzo del nombre de cualquier miembro no estático de la clase. Consideremos, por ejemplo, la siguiente función miembro de nombre reset_id() perteneciente a la interfaz pública de la clase Student:

   class Student {       int id_;       std::string name_;    public:       // constructores y resto de interfaz pública...       void reset_id(int id) { id_ = id; }    };

Podríamos referirnos explícitamente al objeto que invoque dicha función, si así lo deseáramos, a través del puntero this que lo referencia:

   void Student::reset_id(int id) { this->id_ = id; }

GCC 6.1

El equipo encargado del desarrollo de la familia de compiladores GCC acaba de anunciar el lanzamiento inminente de su versión 6.1. En relación a C++, el compilador dará soporte experimental a varias de las especificaciones técnicas (Technical Specifications o simplemente TS) publicadas en los últimos tiempos por el comité de estandarización ISO/IEC 14882 en su afán por mejorar y extender el lenguaje. Concretamente:
  • Concepts TS: Una extensión del sistema de plantillas de clase y de función (templates) que permite la incorporación de restricciones sobre los tipos con los que operan, mejorando sustancialmente la legibilidad de los mensajes de error emitidos por el compilador en caso de no cumplirse dichas ligaduras.
  • File System TS: Biblioteca basada en Boost.Filesystem que permite la gestión avanzada de sistemas de archivos y sus componentes (ficheros, árboles de dirección, etcétera).
  • Library Fundamentals TS: Contiene mejoras en el funcionamiento de clases como std::functional o std::promise, nuevas herramientas como std::any, std::optional o std::basic_string_view, soporte para matrices en std::shared_ptr, etcétera.
  • Transactional Memory TS: Un nuevo modelo de programación concurrente que sincroniza el acceso a datos compartidos por múltiples hilos de ejecución a través de transacciones ejecutadas atómicamente.
Puede encontrarse más información acerca de las nuevas características del compilador en la dirección gcc.gnu.org/gcc-6/changes.html. Para una descripción más detallada de los nuevos TS, consúltese en.cppreference.com/w/cpp/experimental.

Inferencia automática de tipos (auto)

Última actualización: 15 de agosto de 2020.

Artículos de la serie:

Introducción


La inferencia automática de tipos mediante la palabra clave auto --técnica introducida por vez primera en el estándar ISO C++ 2011 y refinada en estándares posteriores [1]-- permite la declaración de variables de forma tal que sus tipos sean deducidos automáticamente a partir de los tipos de sus inicializadores, siguiendo las reglas clásicas de deducción de argumentos en plantillas de función (template-argument-deduction o TAD) [2]. A partir de C++14, la inferencia automática puede ser también empleada en la signatura de una función para requerir que el tipo retornado sea deducido a partir de sus instrucciones de retorno.

Esta potente herramienta de programación fue diseñada por Bjarne Stroustrup a principios de los años 1980, pero tuvo que aguardar hasta su inclusión definitiva en C++11 por motivos de compatibilidad con el lenguaje C.

Por ejemplo, en sustitución de

   std::unique_ptr<int> p = std::make_unique<int>(1);

podemos escribir, sin riesgo de introducir ambigüedad en el código:

   auto p = std::make_unique<int>(1);

de forma que el compilador infiera de forma automática el tipo del puntero inteligente p a partir del tipo retornado por la función std::make_unique<int>, en este caso std::unique_ptr<int>.

Paso de parámetros a funciones. ¿Copiar o referenciar?

Última actualización: Diciembre de 2019

Supongamos que deseamos comunicar a una función la dirección en memoria de una variable con el fin de modificar su valor. Si descartamos la posibilidad de que el objeto pueda ser inválido (y, con ello, el uso de un puntero tradicional y la subsiguiente comprobación de puntero nulo), declararíamos el parámetro de la función como una referencia lvalue al tipo de variable que se desea modificar. A modo de ejemplo, en el siguiente código creamos un objeto obj de tipo Object, el cual es pasado como argumento a una función do_something() con el fin de realizar ciertas modificaciones sobre el mismo:

   class Object;    // ...    void do_something(Object& ob) { /* la función modifica el objeto referenciado */ }    // ...    auto obj = Object{};    do_something(obj); // llamada a función do_something() para modificar el objeto obj