Punteros inteligentes (IV): Propiedad compartida (primera parte)


Propiedad compartida. Bloques de control


La plantilla de clase uniparamétrica std::shared_ptr<> implementa una semántica de propiedad compartida: uno o más objetos std::shared_ptr<> pueden ser propietarios no-exclusivos de un mismo recurso (normalmente, memoria asignada dinámicamente mediante expresiones new). Dicho recurso es liberado una vez que todos los objetos std::shared_ptr<> que lo referencien sean destruidos, reasignados o renuncien a su propiedad, siendo su último propietario el encargado de liberarlo (la política de liberación por defecto es una expresión delete, aunque ésta puede ser personalizada por el usuario). Este comportamiento se consigue a través de un contador de referencias interno, lo que convierte a std::shared_ptr<> en un mecanismo básico de recolección de basura cuando el recurso compartido sea memoria [1].

Punteros inteligentes (III): Propiedad exclusiva (segunda parte)

Políticas de liberación


Ha llegado el momento de analizar cómo configurar la política de liberación a seguir con el objeto apuntado por std::unique_ptr al finalizar el tiempo de vida del puntero inteligente. A modo de ejemplo, empleemos std::unique_ptr para garantizar que un flujo a fichero std::FILE sea cerrado automáticamente al término de un ámbito:

   using File_ptr = std::unique_ptr<std::FILE,                                     decltype([](std::FILE* f){ if (f) std::fclose(f); })>;    {       auto ifile = File_ptr{std::fopen("text.txt", "r")};                 // usamos el fichero en modo lectura...              } // el destructor de File_ptr cierra el fichero automáticamente en este punto

Hemos hecho uso aquí del estándar C++20, que permite la aparición de expresiones lambda en contextos no-evaluados (unevaluated contexts) como decltype. En nuestro código, el objeto std::unique_ptr se hace cargo del puntero std::FILE* retornado por la función std::fopen e inicializa un deleter a partir de la expresión lambda. Dicho deleter es el encargado de cerrar el fichero una vez que el puntero inteligente finalice su tiempo de vida. Observemos, en particular, que en ningún punto se ha efectuado alojamiento dinámico de memoria.

Punteros inteligentes (II): Propiedad exclusiva (primera parte)

Puntero inteligente std::unique_ptr


La plantilla de clase std::unique_ptr<> implementa una semántica de propiedad exclusiva del objeto apuntado. Concretamente, un objeto u de tipo std::unique_ptr<T> almacena un puntero miembro a un segundo objeto de tipo T o derivado, sobre el que se sigue una determinada política de destrucción (configurable por el usuario) cuando u es destruido. La semántica de propiedad exclusiva implica que el puntero inteligente u no pueda copiarse, pues de poder hacerlo acabaríamos con dos punteros propietarios del mismo objeto. Existe, sin embargo, un mecanismo de transferencia de la propiedad que analizaremos en este post.