Bienvenidos sean a este post, hoy veremos otro puntero inteligente.
En el post anterior hablamos sobre el shared_ptr. weak_ptr es una version mas reducida de este pero comparte todas las conductas de este. Al igua que shared_ptr contiene dos punteros, siendo uno el objeto que manejaremos y otro para el bloque de control.
El bloque de control contiene la cantidad de veces que se utiliza el recurso pero tambien contiene las referencias debiles. Esto se hace porque el recurso propio también podría estar apuntado a un puntero débil. Este se referencia a un objeto administrado por una instancia de shared_ptr, pero este no lo pertenece. Es decir, este nos permite acceder y usar el recurso donde shared_ptr es propietario pero sin adueñarse del mismo. Sin embargo, tenemos la posibilidad de convertir una instancia de weak_ptr en una de shared_ptr. usando la funcion lock. Tanto shared_ptr como weak_ptr pueden ser usados para administrar arrays asignadas dinamicamente. Vamos a aplicarlo en un ejemplo:
#include <iostream>
#include <memory>
std::weak_ptr<int> t;
void observar()
{
std::cout << "t.use_count() = " << t.use_count() << " / ";
if (std::shared_ptr<int> ptc = t.lock())
std::cout << "*ptc = " << *ptc << std::endl;
else
std::cout << "t expiro" << std::endl;
}
int main()
{
{
auto pc = std::make_shared<int>(42);
t = pc;
observar();
}
observar();
return 0;
}
Primero crearemos una variable de weak_ptr, y luego definiremos una funcion para observar cuantas copias tenemos del puntero. Para ello tenemos un mensaje que muestra el valor que devuelve use_count y un condicional donde verifica si el objeto de tipo shared_ptr es creado correctamente. Y a este le asignaremos el puntero debil pero mediante lock lo convertirrmos a shared, como mencionamos anteriormente, y mientras se cumple nos mostrara el valor recibido del puntero debil. De lo contrario, nos muestra un mensaje de que expiro el puntero debil. En el main, primero definimos una variable que la haremos compatible y con un valor. Este sera asignado al puntero debil y llamamos a la funcion observar. Este estara dentro de un bloque para diferenciarlo del main y podamos eliminar el objeto antes de que salga del scope. Y antes de finalizar llamaremos nuevamente a observar. Compilemos y veamos como es la salida:
$ ./memoria
t.use_count() = 1 / *ptc = 42
t.use_count() = 0 / t expiro
$
Pueden ver como en el bloque realizo la copia al ser llamado mediante observar. Y cuando salimos del bloque elimina a este objeto y al momento de llamar nuevamente a observar nos informo que desparecio completamente.
Otro buen ejemplo para entenderlo es un cache. Para objetos recientemente accedidos, puede que necesitemos mantenerlo en memoria y por esta razon debemos usar un puntero fuerte. Si periodicamente, revisamos el cache y decidimos cuales son los objetos que no han sido accedidos recientemente. Esto los considera innecesarios y por lo tanto, removeremos al puntero fuerte. Pero que sucede si el objeto esta en uso y otra parte del codigo posee un puntero fuerte a este? Si el cache se deshace de este, no podremos volverlo a encontrar. Por esto, el cache mantiene un puntero debil a los objetos que se necesitan para encontrarlo si permanecen en memoria. Los punteros debiles hacen exactamente esto, nos permiten ubicar objetos si aun se encuentran alrededor. En caso de no ser necesarios se procede a eliminarlos.
En resumen, hoy hemos visto a weak_ptr, que es, para que sirve, como se utiliza, y un par de ejemplos practicos para poder verlo en accion. Espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donatión
It’s for site maintenance, thanks!
$1.50
