Manejo de memoria dinamica en C++

  • Published on
    14-Oct-2015

  • View
    31

  • Download
    0

Embed Size (px)

Transcript

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 1 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y Automtica Universidad de Salamanca (versin Febrero 2003)

    Clases y manejo de memoria dinmica en C++ Repaso a las funciones de manejo de memoria dinmica en C ............................................................................1

    Funcin calloc()...................................................................................................................................................1 Funcin malloc() .................................................................................................................................................2 Funcin realloc() .................................................................................................................................................2 Funcin free() ......................................................................................................................................................3

    El operador new frente a malloc ............................................................................................................................3 El operador delete frente a free ..............................................................................................................................8 Sobrecarga de new y de delete ................................................................................................................................9

    Sobrecarga de new y delete respecto a una clase especfica.............................................................................11 Clases con punteros miembros .............................................................................................................................14 El Puntero this ......................................................................................................................................................22

    Funciones estticas y el puntero this .................................................................................................................24 Paso y retorno de objetos ......................................................................................................................................24 Paso y retorno de referencias a objetos................................................................................................................26 Ejercicios propuestos ............................................................................................................................................27

    Repaso a las funciones de manejo de memoria dinmica en C

    Funcin calloc() Prototipo: void *calloc(int num, int tam); Archivo cabecera: stdlib.h Valor devuelto: Devuelve un puntero al primer byte del bloque de memoria reservada, o un puntero NULL en el caso de no haberse podido reservar el bloque de memoria solicitado Finalidad: Reserva un bloque de memoria para almacenar num elementos de tam bytes cada uno de ellos. Todo el bloque de memoria queda iniciado a 0. num: indica el nmero de elementos con la misma estructura que ocuparn el bloque de memoria reservado. tam: indica el tamao en bytes de cada uno de los elementos que van a ocupar el bloque de memoria

    reservada. La cantidad de memoria reservada viene determinada por el resultado que se obtiene al multiplicar el nmero de elementos a almacenar en el bloque de memoria por el tamao en bytes de cada uno de esos elementos, es decir, num * tam. El uso de esta funcin se puede ilustrar con el siguiente ejemplo:

    int n=100, *pt; ... pt = ( int * ) calloc (n, sizeof(int));

    En este ejemplo la funcin calloc reserva un bloque de memoria de n enteros, y retorna un puntero void a dicho bloque, o NULL si n fuera 0 o se produjera un error al no poder reservar suficiente espacio para reservar la

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 2 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y Automtica Universidad de Salamanca (versin Febrero 2003)

    memoria solicitada. Sobre el puntero que se retorna se debe hacer una operacin de cast apropiada, para asignarlo al puntero del tipo que se est tratando.

    Funcin malloc() Prototipo: void *malloc(int tam); Archivo cabecera: stdlib.h Valor devuelto: Devuelve un puntero al primer byte del bloque de memoria reservada, o un puntero NULL en el caso de no haberse podido reservar el bloque de memoria solicitado Finalidad: Reserva un bloque de memoria de tam bytes. tam: indica el tamao en bytes del bloque de memoria que se desea reservar. La cantidad de memoria reservada ser de tam bytes. El uso de esta funcin se puede ilustrar con el siguiente ejemplo:

    struct Registro *ptr_reg; ptr_reg = ( struct Registro * ) malloc (sizeof (struct Registro));

    La funcin malloc reserva un bloque de memoria lo suficientemente grande como para acoger por completo al tipo de dato, y retorna un puntero void a dicho bloque, o NULL si el tamao del argumento es 0 o se ha producido un error al no poder reservar suficiente espacio para alojar al tipo de dato. Sobre el puntero que se retorna se debe hacer una operacin de cast apropiada, para asignarlo al puntero del tipo que se est tratando.

    Funcin realloc() Prototipo: void *realloc(void *ptr, int nuevo_tamao); Archivo cabecera: stdlib.h Valor devuelto: Devuelve un puntero al primer byte del bloque de memoria reservada, o un puntero NULL en el caso de no haberse podido reservar el bloque de memoria solicitado Finalidad: Cambia el tamao del bloque de memoria apuntada por ptr al nuevo tamao indicado por nuevo_tamao ptr: puntero que apunta al bloque de memoria reservado. nuevo_tamao: valor en bytes que indica el nuevo tamao del bloque de memoria apuntado por ptr y que

    puede ser mayor o menor que el original. En estas tres funciones es importante comprobar que el puntero devuelto por ellas no es un puntero nulo (NULL) antes de hacer uso del bloque de memoria reservado.

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 3 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y Automtica Universidad de Salamanca (versin Febrero 2003)

    Funcin free() Prototipo: void free(void *ptr); Archivo cabecera: stdlib.h Valor devuelto: Ninguno Finalidad: Libera el bloque de memoria apuntada por ptr y que previamente ha sido asignado mediante malloc() o calloc(). ptr: variable puntero que debe contener la direccin de memoria del primer byte del bloque de memoria que

    deseamos liberar. En caso de que no sea un puntero previamente reservado por malloc() o calloc(), la llamada a la funcin free() puede ocasionar una parada o interrupcin del sistema.

    El operador new frente a malloc En el lenguaje C, la regin de memoria que est disponible a la hora de la ejecucin recibe el nombre de heap. En C++ el espacio de memoria disponible se conoce como almacenamiento libre1. La diferencia entre los dos se encuentra en las funciones que se utilicen para el acceder a esta memoria. El mtodo para solicitar memoria del heap en C se basa en el uso de la funcin malloc y sus derivadas (calloc, realloc, ...). En C++ no es correcto utilizar malloc para alojar de forma dinmica una nueva instancia de una clase. La razn es que si se usa malloc, se pierden las ventajas que nos ofrecen los constructores, ya que se llama al constructor de la clase cada vez que se crea un objeto. Si se usa malloc para crear un objeto, se tiene un puntero a un bloque de memoria sin iniciar. Entonces se pueden hacer llamadas a mtodos con objetos que no estn bien construidos, y que por lo tanto van a dar resultados errneos. La tcnica ms adecuada es utilizar la alternativa que ofrece C++ mediante el operador new. El operador new conoce la clase del objeto, o el tipo de la variable, que se quiere alojar en el almacenamiento libre. De esta forma este operador llama automticamente al constructor que corresponda, dependiendo de los argumentos que se especifiquen, para iniciar la memoria que ha reservado. La forma de utilizar este operador es la siguiente: = new [];

    De la sintaxis de new se puede deducir que no es una funcin, y que por lo tanto no tiene una lista de argumentos entre parntesis. Es un operador que se aplica al nombre del tipo, pero no se tiene que realizar un cast 2 ni utilizar el operador sizeof para determinar su tamao, porque new conoce el tipo de dato y su tamao. Si new no encuentra espacio para alojar lo que se le pide, devuelve 03. El operador new reemplaza a las funciones malloc y calloc de la biblioteca estndar de C, pero no sustituye a realloc. La funcin realloc puede ser simulada, pero la aproximacin que se haga supondr siempre un aumento

    1Free store. 2 El compilador comprueba que el tipo del puntero que devuelve new y el tipo del puntero al que se asigna son del mismo tipo. En caso contrario genera un error. 3 En C++ un puntero nulo vale 0 en lugar de NULL.

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 4 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y Automtica Universidad de Salamanca (versin Febrero 2003)

    de las lneas del cdigo fuente, as como conocer el tamao original del espacio reservado mediante el puntero que se va cambiar. Pero afortunadamente se puede utilizar generalmente realloc para cambiar el tamao del espacio reservado con new. Como se ha dicho, con new se puede reservar espacio para cualquier tipo de dato, siendo muy utilizado para reservar espacio para matrices4. Un ejemplo:

    float *centros; centros = new float[numero];

    Para ilustrar todo lo visto hasta el momento del operador new se ha realizado este sencillo programa de ejemplo: // Programa: malloc versus new // Fichero: MALVNEW.CPP #include #include #include class Prueba { int i, j; char *s; public: Prueba() { // Constructor por defecto i=j=5; s=new char[5]; strncpy(s, "Hola", 5); } Prueba(char *cad, int a, int b) { // Constructor con parmetros i=a; j=b; s=new char[strlen(cad)+1]; strcpy(s, cad); } ~Prueba () {delete [] s;} // Destructor int miembro(void) { // Funcin para mostrar los datos de la clase cout

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 5 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y Automtica Universidad de Salamanca (versin Febrero 2003)

    void main (void) { // Creamos un objeto dinmico con malloc Prueba *P1; P1=(Prueba *) malloc (sizeof (Prueba)); // Y nos vamos a estrellar: Salen caracteres raros por pantalla e // incluso se puede colgar el programa cout

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 6 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y Automtica Universidad de Salamanca (versin Febrero 2003)

    C++ define un puntero a funcin, de forma que cuando ocurre un error, la funcin a la que apunta el puntero es llamada. La definicin de dicho puntero es: void (* _new_handler)(); El uso de este puntero tiene el inconveniente de no ser estndar. Por ello se recomienda el uso de una funcin de biblioteca definida en new.h, y que se llama set_new_handler, que toma como argumento un puntero a funcin, y asigna la funcin al puntero _new_handler. Aunque este segundo mtodo es ms comn, y por lo tanto ms conveniente, tampoco es estndar7. // Programa: Manejo de errores en la reserva de espacio con new // Versin Borland C++ // Fichero: NEW_ERR.CPP #include #include #include #define PASO 20000 void MemoriaInsuficiente(void) { cerr

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 7 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y Automtica Universidad de Salamanca (versin Febrero 2003)

    // Programa: Manejo de errores en la reserva de espacio con new // Versin Microsoft C++ // Fichero: NEW_ERR.CPP #include #include #include int MemoriaInsuficiente(size_t size) { cerr

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 8 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y Automtica Universidad de Salamanca (versin Febrero 2003)

    El operador delete frente a free El operador delete se puede decir que es para new, lo que free para malloc. Esto es, libera los bloques de memoria, dejndolos listos para futuras reservas. La sintaxis de delete es muy sencilla: delete ; Cuando se trata de liberar el espacio asociado un puntero a un objeto, delete de forma automtica llama al destructor. El operador delete se debe utilizar slo con punteros que retorne new. Mientras que la funcin free se debe usar con punteros que apunten a zonas de memoria reservadas mediante funciones derivadas de malloc. De no hacerse as, y dependiendo de los compiladores, puede causar graves problemas9. Si se intenta liberar dos veces un mismo puntero, los resultados pueden ser catastrficos. Estas dos circunstancias deben ser controladas por el programador, ya que el compilador no las detecta. Se puede liberar un puntero nulo sin consecuencias adversas. El uso de delete con los tipos preestablecidos no tiene misterios, salvo en el caso de las matrices, que se debe usar la siguiente sintaxis: delete [tamao] ; En la mayora de los compiladores basta con poner los corchetes vacos, ya que ignoran el nmero que se ponga entre ellos. Un sencillo ejemplo del uso del operador unario delete puede ser el siguiente: // Programa: Uso de delete // Fichero: DELETE1.CPP #include #include void main (void) {

    int *i, *vi;

    i=new int; *i=6;

    vi= new int[2];

    vi[0]=0; vi[1]=1;

    cout

  • Programacin Orientada a Objetos 3 Clases manejo de memoria dinmica en C++ - 9 -

    Ingeniera Tcnica en Informtica de Sistemas (3er curso) Departamento de Informtica y...