Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
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 />
✐