Anuncios

Bienvenidos sean a este post, hoy veremos la herramienta para administrar la memoria.

Anuncios
Anuncios

En el post anterior, hablamos sobre el concepto de colector de basura. Y si bien, este es muy util para muchos lenguajes tambien mencionamos que C++ puede sobrevivir sin uno, como lo hizo hasta ahora. Principalmente porque usamos al operador delete tanto de forma manual como de manera automatica. Un caso que ya analizamos fue cuando hablamos de los contenedores STL, como son vector y list. Estos tienen distintas maneras de manejar la memoria. De manera predeterminada, un contenedor tiene un allocator de memoria especifico y este es el encargado de ubicar y remover los elementos del contenedor en memoria. Hoy vamos a hablar un poco mas sobre este tema.

Anuncios
Anuncios

Los allocator estan pensados para proveer un control a la administracion de memoria de un contenedor. Podemos decir que es un colector de basura avanzado para los contenedores de C++. En el post anterior, vimos un colector de basura basico pero mal implementado porque si bien en la teoria deberia funcionar pero en la practica no. Si comparamos a la clase Recolector y al allocator de C++, notaremos que comparten muchas similitudes. En la clase del post anterior teniamos dos funciones llamadas ubicar y desubicar, y en la libreria memory tenemos dos funciones: allocate y desallocate, que cumplen tareas similares a las anteriores respectivamente. Veamos como es la definicion de la funcion allocate:

[[nodiscard]] constexpr T* allocate(std::size_t num);
Anuncios

Aqui tenemos dos curiosidades, la primera es el argumento. Este es un valor que representa la cantidad de objetos del tipo generico que se ubicaran en memoria. Y la siguiente es nodiscard, este atributo nos indica que el resultado no debe ser descartado por el llamador. En caso contrario, el compilador mostrara un mensaje de aviso. Veamos como es la definicion de la funcion deallocate:

constexpr void deallocate(T* p, std::size_t n);
Anuncios

En este caso, la funcion recibe dos argumentos. El primero sera el puntero generado por allocate donde esta el objeto y el segundo son la cantidad que eliminaremos. En contraposicion de lo que hicimos al momento de ubicarlos. Veamos un ejemplo simple:

#include <iostream>
#include <memory>

int main()
{
  std::allocator<int> IntAlloc;
  int* ptr = IntAlloc.allocate(5);
  std::allocator_traits<decltype(IntAlloc)>::construct(IntAlloc, ptr + 1, 42);
  IntAlloc.deallocate(ptr, 5);
}
Anuncios
Anuncios

Primero definimos un objeto de allocator del tipo int. Lo siguiente es un puntero para el objeto anterior y en este usaremos a allocate para que ubique cinco espacios de tipo int en memoria. Lo siguiente es un constructor pero para un allocator de traits. Observen como pasamos el tipo, porque para el constructor tome al objeto de allocator como un tipo lo debemos pasar con decltype, de lo contrario no lo tomara como un tipo y fallara al compilarlo. Este lo usaremos para que establezca el valor de 42 en la segunda posicion que establecimos anteriorrmente. Y la ultima linea, es para desubicar a todos los elementos ubicados anteriormente. Observen que pasamos al puntero, no al objeto, y la cantidad que establecimos.

Anuncios

En la vida real no usaremos estas dos instrucciones para nuestros proyectos directamente. Pero esto no quita que podemos usarlo para crear administradores de memoria personalizadas para algunas situaciones. Ya mencionamos que los contenedores STL usan mayoritamente allocator porque son de estructuras y conductas diferentes. Esto lleva a que necesiten conductas personalizadas para la ubicacion y remocion de memoria.

Anuncios

En resumen, hoy hemos visto a allocator, que es, para que sirve, como se utiliza, y un ejemplo practico para entender el concepto. 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.

Anuncios
pp258

Donatión

It’s for site maintenance, thanks!

$1.50