Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
✐<br />
✐<br />
✐<br />
“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 382 — #420<br />
✐<br />
Capítulo 13. Creación dinámica de objetos<br />
malloc() con calloc() o realloc()).<br />
Se invoca malloc(), que pide un bloque de memoria. (Este código realm<strong>en</strong>te<br />
puede ser parte de malloc()).<br />
Ahora ti<strong>en</strong>e lugar la búsqueda de un bloque de tamaño adecuado de <strong>en</strong>tre los<br />
bloques libres. Esto requiere la comprobación de un mapa o directorio de algún tipo<br />
que lleve el registro de los bloques disponibles y de los que están <strong>en</strong> uso. Es un<br />
proceso rápido, pero puede que necesite varias pruebas, es pues un proceso no determinista.<br />
Dicho de otro modo, no se puede contar con que malloc() tarde siempre<br />
exactam<strong>en</strong>te el mismo tiempo <strong>en</strong> cada búsqueda.<br />
Antes de <strong>en</strong>tregar el puntero del bloque obt<strong>en</strong>ido, hay que registrar <strong>en</strong> alguna<br />
parte su tamaño y localización para que malloc() no lo vuelva a usar y para que<br />
cuando se produzca la llamada a free(), el sistema sepa cuánto espacio ha de liberar.<br />
El modo <strong>en</strong> que se implem<strong>en</strong>tan todas estas operaciones puede variar mucho.<br />
No hay nada que impida que puedan implem<strong>en</strong>tarse las primitivas de asignación<br />
de memoria <strong>en</strong> el conjunto de instrucciones del procesador. Si es sufici<strong>en</strong>tem<strong>en</strong>te curioso,<br />
pued<strong>en</strong> escribir programas que permitan averiguar cómo está implem<strong>en</strong>tada<br />
malloc(). Si dispone de él, puede leer el código fu<strong>en</strong>te de la biblioteca de funciones<br />
de C, si no, siempre está disponible el de GNU C.<br />
13.2. Rediseño de los ejemplos anteriores<br />
Puede reescribirse el ejemplo Stash que vimos anteriorm<strong>en</strong>te <strong>en</strong> el libro, haci<strong>en</strong>do<br />
uso de los operadores new y delete, con las características que se han visto<br />
desde <strong>en</strong>tonces. A la vista del nuevo código se pued<strong>en</strong> repasar estas cuestiones.<br />
Hasta este punto del libro, ninguna de las clases Stash ni Stack poseerán los<br />
objetos a los que apuntan; es decir, cuando el objeto Stash o Stack sale de ámbito,<br />
no se invoca delete para cada uno de los objetos a los que apunta. La razón por la<br />
que eso no es posible es porque, <strong>en</strong> un int<strong>en</strong>to de conseguir más g<strong>en</strong>eralidad, utilizan<br />
punteros void. Usar delete con punteros void libera el bloque de memoria pero,<br />
al no existir información de tipo, el compilador no sabe qué destructor debe invocar.<br />
13.2.1. delete void* probablem<strong>en</strong>te es un error<br />
Es necesario puntualizar que, llamar a delete con un argum<strong>en</strong>to void* es casi<br />
con seguridad un error <strong>en</strong> el programa, a no ser que el puntero apunte a un objeto<br />
muy simple; <strong>en</strong> particular, que no t<strong>en</strong>ga un destructor. He aquí un ejemplo ilustrativo:<br />
//: C13:BadVoidPointerDeletion.cpp<br />
// Deleting void pointers can cause memory leaks<br />
#include <br />
using namespace std;<br />
class Object {<br />
void* data; // Some storage<br />
const int size;<br />
const char id;<br />
public:<br />
Object(int sz, char c) : size(sz), id(c) {<br />
382<br />
✐<br />
✐<br />
✐<br />
✐