Attention! Your ePaper is waiting for publication!
By publishing your document, the content will be optimally indexed by Google via AI and sorted into the right category for over 500 million ePaper readers on YUMPU.
This will ensure high visibility and many readers!
✐ ✐ ✐ “Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 380 — #418 ✐ Capítulo 13. Creación dinámica de objetos que el usuario puede olvidar inicializar el objeto antes de usarlo, introduci<strong>en</strong>do así una importante fu<strong>en</strong>te de problemas. Como consecu<strong>en</strong>cia, muchos programadores <strong>en</strong>cu<strong>en</strong>tran muy confusas y complicadas las funciones de asignación dinámica de la memoria <strong>en</strong> C. No es muy difícil <strong>en</strong>contrar programadores que, usando máquinas con memoria virtual, usan vectores <strong>en</strong>ormes <strong>en</strong> el área de almac<strong>en</strong>ami<strong>en</strong>to estático para evitar t<strong>en</strong>er que tratar con la asignación dinámica. Dado que <strong>C++</strong> int<strong>en</strong>ta facilitar el uso de la biblioteca a los programadores ocasionales, no es aceptable la forma de abordar la asignación dinámica <strong>en</strong> C. 13.1.2. El operador new La solución que ofrece <strong>C++</strong> consiste <strong>en</strong> combinar la serie de acciones necesarias para la creación de un objeto <strong>en</strong> un único operador llamado >new. Cuando se crea un objeto mediante el operador >new, éste se <strong>en</strong>carga de obt<strong>en</strong>er el espacio necesario para el objeto y de llamar a su constructor. Cuando se ejecuta el código: MyType *fp = new MyType(1,2); se asigna espacio mediante alguna llamada equival<strong>en</strong>te a >malloc(sizeof(MyType)) --con frecu<strong>en</strong>cia es así, literalm<strong>en</strong>te--, y usando la dirección obt<strong>en</strong>ida como puntero >this, y (1, 2) como argum<strong>en</strong>tos, se llama al constructor de la clase M- yType. Para cuando está disponible, el valor de retorno de new es ya un puntero válido a un objeto inicializado. Además es del tipo correcto, lo que hace innecesaria la conversión. El operador new por defecto, comprueba el éxito o fracaso de la asignación de memoria como paso previo a la llamada al constructor, haci<strong>en</strong>do innecesaria y redundante la posterior comprobación. Más adelante <strong>en</strong> este capítulo se verá qué sucede si se produce este fallo. En las expresiones con new se puede usar cualquiera de los constructores disponibles para una clase. Si éste no ti<strong>en</strong>e argum<strong>en</strong>tos, se escribe la expresión sin lista de argum<strong>en</strong>tos MyType *fp = new MyType; Es notable la simpleza alcanzada <strong>en</strong> la creación dinámica de objetos: una única expresión realiza todo el trabajo de cálculo de tamaño, asignación, comprobaciones de seguridad y conversión de tipo. Esto hace que la creación dinámica de objetos sea tan s<strong>en</strong>cilla como la creación <strong>en</strong> la pila. 13.1.3. El operador delete El complem<strong>en</strong>to a la expresión new es la expresión delete, que primero llama al destructor y después libera la memoria (a m<strong>en</strong>udo mediante una llamada a free(- )). El argum<strong>en</strong>to para una expresión con delete debe ser una dirección: un puntero a objeto creado mediante new. delete fp; 380 ✐ ✐ ✐ ✐
✐ ✐ ✐ “Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 381 — #419 ✐ 13.1. Creación de objetos Esta expresión destruye el objeto y después libera el espacio dinámicam<strong>en</strong>te asignado al objeto MyType El uso del operador delete debe limitarse a los objetos que hayan sido creados mediante new. Las consecu<strong>en</strong>cias de aplicar el operador delete a los objetos creados con malloc(), calloc() o realloc() no están definidas. Dado que la mayoría de las implem<strong>en</strong>taciones por defecto de new y delete usan malloc() y free(), el resultado será probablem<strong>en</strong>te la liberación de la memoria sin la llamada al destructor. No ocurre nada si el puntero que se le pasa a delete es nulo. Por esa razón, a m<strong>en</strong>udo se recomi<strong>en</strong>da asignar cero al puntero inmediatam<strong>en</strong>te después de usar delete; se evita así que pueda ser usado de nuevo como argum<strong>en</strong>to para delete. Tratar de destruir un objeto más de una vez es un error de consecu<strong>en</strong>cias imprevisibles. 13.1.4. Un ejemplo s<strong>en</strong>cillo El sigui<strong>en</strong>te ejemplo demuestra que la inicialización ti<strong>en</strong>e lugar: //: C13:Tree.h #ifndef TREE_H #define TREE_H #include class Tree { int height; public: Tree(int treeHeight) : height(treeHeight) {} ~Tree() { std::cout