13.01.2015 Views

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

✐<br />

✐<br />

✐<br />

“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 146 — #184<br />

✐<br />

Capítulo 4. Abstracción de Datos<br />

De modo que con new Tipo se obt<strong>en</strong>drá un puntero a un objeto de tipo Tipo, y con<br />

new int obt<strong>en</strong>drá un puntero a un int. Si quiere un nuevo array de unsigned char<br />

la expresión devolverá un puntero al primer elem<strong>en</strong>to de dicho array. El compilador<br />

verificará que se asigne lo que devuelve la expresión-new a una variable puntero del<br />

tipo adecuado.<br />

Por supuesto, es posible que al pedir memoria, la petición falle, por ejemplo, si<br />

no hay más memoria libre <strong>en</strong> el sistema. Como verá más adelante, <strong>C++</strong> cu<strong>en</strong>ta con<br />

mecanismos que <strong>en</strong>tran <strong>en</strong> juego cuando la operación de asignación de memoria no<br />

se puede satisfacer.<br />

Una vez que se ha obt<strong>en</strong>ido un nuevo espacio de almac<strong>en</strong>ami<strong>en</strong>to, los datos que<br />

estaban <strong>en</strong> el antiguo se deb<strong>en</strong> copiar al nuevo. Esto se hace, nuevam<strong>en</strong>te, <strong>en</strong> un<br />

bucle, utilizando la notación de índexado de arrays, copiando un byte <strong>en</strong> cada iteración<br />

del bucle. Una vez finalizada esta copia, ya no se necesitan los datos que están<br />

<strong>en</strong> el espacio de almac<strong>en</strong>ami<strong>en</strong>to original por lo que se pued<strong>en</strong> liberar de la memoria<br />

para que otras partes del programa puedan usarlo cuando lo necesit<strong>en</strong>. La palabra<br />

reservada delete es el complem<strong>en</strong>to de new y se debe utilizar sobre todas aquellas<br />

variables a las cuales se les haya asignado memoria con new. (Si se olvida de utilizar<br />

delete esa memoria queda in-utilizable. Si estas fugas de memoria (memory leak)<br />

son demasiado abundantes, la memoria disponible se acabará.) Existe una sintaxis<br />

especial cuando se libera un array. Es como si recordara al compilador que ese puntero<br />

no apunta sólo a un objeto, sino a un array de objetos; se deb<strong>en</strong> poner un par de<br />

corchetes delante del puntero que se quiere liberar:<br />

delete []myArray;<br />

Una vez liberado el antiguo espacio de almac<strong>en</strong>ami<strong>en</strong>to, se puede asignar el puntero<br />

del nuevo espacio de memoria al puntero storage, se actualiza quantity y<br />

con eso inflate() ha terminado su trabajo.<br />

En este punto es bu<strong>en</strong>o notar que el administrador de memoria del montículo><br />

es bastante primitivo. Nos facilita trozos de memoria cuando se lo pedimos con new<br />

y los libera cuando invocamos a delete. Si un programa asigna y libera memoria<br />

muchas veces, terminaremos con un montículo fragm<strong>en</strong>tado, es decir un montículo<br />

<strong>en</strong> el que si bi<strong>en</strong> puede haber memoria libre utilizable, los trozos de memoria están<br />

divididos de tal modo que no exista un trozo que sea lo sufici<strong>en</strong>tem<strong>en</strong>te grande para<br />

las necesidades concretas <strong>en</strong> un mom<strong>en</strong>to dado. Lam<strong>en</strong>tablem<strong>en</strong>te no existe una<br />

capacidad inher<strong>en</strong>te del l<strong>en</strong>guaje para efectuar defragm<strong>en</strong>taciones del montículo. Un<br />

defragm<strong>en</strong>tador del montículo complica las cosas dado que ti<strong>en</strong>e que mover pedazos<br />

de memoria, y por lo tanto, hacer que los punteros dej<strong>en</strong> de apuntar a valores<br />

válidos. Algunos <strong>en</strong>tornos operativos vi<strong>en</strong><strong>en</strong> con este tipo de facilidades pero obligan<br />

al programador a utilizar manejadores de memoria especiales <strong>en</strong> lugar de punteros<br />

(estos manipuladores se pued<strong>en</strong> convertir temporalm<strong>en</strong>te <strong>en</strong> punteros una vez<br />

bloqueada la memoria para que el defragm<strong>en</strong>tador del montículo no la modifique).<br />

También podemos construir nosotros mismos uno de estos artilugios, aunque no es<br />

una tarea s<strong>en</strong>cilla.<br />

Cuando creamos una variable <strong>en</strong> la pila <strong>en</strong> tiempo de compilación, el mismo compilador<br />

es qui<strong>en</strong> se <strong>en</strong>carga de crearla y liberar la memoria ocupada por ella automáticam<strong>en</strong>te.<br />

Conoce exactam<strong>en</strong>te el tamaño y la duración de este tipo de variables<br />

dada por las reglas de ámbito. Sin embargo, <strong>en</strong> el caso de las variables almac<strong>en</strong>adas<br />

dinámicam<strong>en</strong>te, el compilador no poseerá información ni del tamaño requerido por<br />

las mismas, ni de su duración. Esto significa que el compilador no puede <strong>en</strong>cargarse<br />

de liberar automáticam<strong>en</strong>te la memoria ocupada por este tipo de variables y de aquí<br />

146<br />

✐<br />

✐<br />

✐<br />

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!