13.5. Ejercicios

Las soluciones a los ejercicios se pueden encontrar en el documento electrónico titulado «The Thinking in C++ Annotated Solution Guide», disponible por poco dinero en www.BruceEckel.com.

  1. Crear una clase Counted que contenga un int id y un static int count. El constructor por defecto debe empezar con Counted():id(count++){. También deberá mostrar mensajes con su id, además de alguno que muestre que se está creando. El destructor debe mostrar que está siendo destruido y su id. Probar su funcionamiento.

  2. Compruebe que new y delete llaman siempre a constructores y destructores, creando mediante el uso de new un objeto de la clase Counted del ejercicio 1, y destruyéndolo después con delete. Cree y destruya un vector de Counted en el montículo.

  3. Cree un objeto de la clase PStash, y llénelo de los objetos del ejercicio 1. Observe lo que sucede cuando el objeto PStash sale de su ámbito y es llamado su destructor.

  4. Cree un vector de Counted* y cárguelo con punteros a objetos Counted. Recorra el vector llamando imprimiendo cada objeto, repita este paso y elimínelos uno a uno.

  5. Repita el ejercicio 4 añadiendo una función miembro f() de Counted que muestre un mensaje. Recorra el vector llamando a f() para cada objeto del vector.

  6. Repita el ejercicio 5 usando un objeto PStash.

  7. Repita el ejercicio 5 usando Stack4.h del capítulo 9.

  8. Cree mediante asignación dinámica un vector de objetos de clase Counted. Llame a delete con el puntero resultante como argumento, sin usar el operador subíndice []. Explique el resultado.

  9. Cree un objeto de clase Counted mediante new, convierta el puntero resultante a void* y luego bórrelo. Explique el resultado.

  10. Compile y ejecute el programa NewHandler.cpp en su ordenador. A partir del número resultante, calcule la cantidad de memoria libre disponible para su programa.

  11. Cree una clase y defina en ella operadores de sobrecarga para new y delete, para objetos simples y para vectores de objetos. Demuestre que ambas versiones funcionan.

  12. Diseñe un test que le permita evaluar de forma aproximada la mejora en velocidad obtenida en Framis.cpp con el uso de las versiones adaptadas de new y delete, respecto de la obtenida con las globales .

  13. Modifique NoMemory.cpp para que contenga un vector de enteros y realmente obtenga memoria en lugar de disparar bad_alloc. Establezca un bucle while en el cuerpo de main() similar al que existe en NewHandler.cpp para agotar la memoria. Observe lo que sucede en el caso de que su operador new no compruebe el éxito de la asignación de memoria. Añada después esa comprobación a su operador new y la llamada a throw bad_alloc.

  14. Cree una clase y defina un operador new de emplazamiento, con un string como segundo argumento. Defina un vector de string, en el que se almacenará este segundo argumento a cada llamada a new. El operador new de emplazamiento asignará bloques de manera normal. En main(), haga llamadas a este operador new pasándole como argumentos cadenas de caracteres que describan las llamadas. Para ello, puede hacer uso de las macros __FILE__ y __LINE__ del preprocesador.

  15. Modifique ArrayOperatorNew.cpp definiendo un vector estático de Widget* que añada la dirección de cada uno de los objetos Widget asignados con new, y la retire cuando sea liberada mediante delete. Puede que necesite buscar información sebre vectores en la documentación de la biblioteca estándar de C++, o en el segundo volumen de este libro que está disponible en la web del autor. Cree una segunda clase a la que llamará MemoryChecker, que contenga un destructor que muestre el número de punteros a Widget en su vector. Diseñe un programa con una única instancia global de MemoryChecker, y en main(), cree y destruya dinámicamente varios objetos y vectores de objetos Widget. Observe que MemoryCheck revela fugas de memoria.