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 386 — #424<br />

✐<br />

Capítulo 13. Creación dinámica de objetos<br />

memset(st, 0, (quantity + increase) * psz);<br />

memcpy(st, storage, quantity * psz);<br />

quantity += increase;<br />

delete []storage; // Old storage<br />

storage = st; // Point to new memory<br />

} ///:~<br />

La función add() es, <strong>en</strong> efecto, la misma que antes si exceptuamos el hecho de<br />

que lo que se almac<strong>en</strong>a ahora es un puntero a un objeto <strong>en</strong> lugar de una copia del<br />

objeto.<br />

El código de inflate() ha sido modificado para gestionar la asignación de memoria<br />

para un vector de void*, a difer<strong>en</strong>cia del diseño previo, que sólo trataba con<br />

bytes. Aquí, <strong>en</strong> lugar de usar el método de copia por el índice del vector, se pone<br />

primero a cero el vector usando la función memset() de la biblioteca estándar de<br />

C, aunque esto no sea estrictam<strong>en</strong>te necesario ya que, presumiblem<strong>en</strong>te, PStash<br />

manipulará la memoria de forma adecuada, pero a veces no es muy costoso añadir<br />

un poco más de seguridad. A continuación, se copian al nuevo vector usando m-<br />

emcpy() los datos exist<strong>en</strong>tes <strong>en</strong> el antiguo. Con frecu<strong>en</strong>cia verá que las funciones<br />

memcpy() y memset() han sido optimizadas <strong>en</strong> cuanto al tiempo de proceso, de<br />

modo que pued<strong>en</strong> ser más rápidas que los bucles anteriorm<strong>en</strong>te vistos. No obstante,<br />

una función como inflate() no es probable que sea llamada con la frecu<strong>en</strong>cia<br />

necesaria para que la difer<strong>en</strong>cia sea palpable. En cualquier caso, el hecho de que<br />

las llamadas a función sean más concisas que los bucles, puede ayudar a prev<strong>en</strong>ir<br />

errores de programación.<br />

Para dejar definitivam<strong>en</strong>te la responsabilidad de la limpieza de los objetos sobre<br />

los hombros del programador cli<strong>en</strong>te, se proporcionan dos formas de acceder a<br />

los punteros <strong>en</strong> PStash: el operador [], que devuelve el puntero sin eliminarlo del<br />

cont<strong>en</strong>edor, y un segundo método remove() que además de devolver el puntero lo<br />

elimina del cont<strong>en</strong>edor, poni<strong>en</strong>do a cero la posición que ocupaba. Cuando se produce<br />

la llamada al destructor de PStash, se prueba si han sido previam<strong>en</strong>te retirados<br />

todos los punteros, si no es así, se notifica, de modo que es posible prev<strong>en</strong>ir la fuga<br />

de memoria. Se verán otras soluciones mas elegantes <strong>en</strong> capítulos posteriores.<br />

Una prueba<br />

Aquí aparece el programa de prueba de Stash, reescrito para PStash:<br />

//: C13:PStashTest.cpp<br />

//{L} PStash<br />

// Test of pointer Stash<br />

#include "PStash.h"<br />

#include "../require.h"<br />

#include <br />

#include <br />

#include <br />

using namespace std;<br />

int main() {<br />

PStash intStash;<br />

// ’new’ works with built-in types, too. Note<br />

// the "pseudo-constructor" syntax:<br />

for(int i = 0; i < 25; i++)<br />

intStash.add(new int(i));<br />

386<br />

✐<br />

✐<br />

✐<br />

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

Saved successfully!

Ooh no, something went wrong!