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. Cree 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 su id y un mensaje que indique que se está creando. El destructor debe mostrar que está siendo destruido y su id. Pruebe 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 también un array de Counted en el montículo.

  3. Cree un objeto de la clase PStash y llénelo con nuevos objetos (creados con new) del ejercicio 1. Observe lo que sucede cuando el objeto PStash sale de su ámbito y se llama a su destructor.

  4. Cree un vector de Counted* y cárguelo con punteros a nuevos objetos Counted (del ejercicio 1). Recorra el vector imprimiendo cada objeto y, después, recórralo de nuevo y elimínelos uno a uno.

  5. Repita el ejercicio 4 añadiendo a Counted una función miembro f() 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 array de objetos de clase Counted. Llame a delete con el puntero resultante como argumento, sin usar los corchetes []. 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 computador. A partir del número resultante, calcule la cantidad de memoria libre disponible para su programa.

  11. Cree una clase y sobrecargue en ella los operadores new y delete, tanto las versiones para objetos simples como las versiones para arrays. Demuestre que ambas versiones funcionan.

  12. Diseñe una prueba 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 array de enteros y realmente obtenga memoria en lugar de lanzar 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 haga que lance la excepción con throw bad_alloc.

  14. Cree una clase y defina un operador new de emplazamiento, con un string como segundo argumento. Defina un vector estático de string, en el que se almacenará este segundo argumento en 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 sobre vectores en la documentación de la Librería 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 arrays de objetos Widget. Demuestre que MemoryChecker revela fugas de memoria.