Gestión Dinámica de la Memoria

25
Ing. Julio César Canelón Rangel Actualizado: Abril 2007 Gestión Dinámica de la Memoria

Transcript of Gestión Dinámica de la Memoria

Ing. Julio César Canelón RangelActualizado: Abril 2007

Gestión Dinámica de la Memoria

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros (apuntadores)

Cuando el compilador encuentra declaraciones como: int varInt = 1234; double varDouble = 1.2364; char varChar = ‘a’;

Se crean dichas variables, lo cual significa que: Se reserva la memoria para un valor del tipo especificado. El nombre de la variable se asocia con la dirección de esa

memoria. La memoria se inicializa con valores procedentes a la

declaración (si los hay)

Ing. Julio César Canelón RangelActualizado: Abril 2007

Mapa de Memoria0x00528320

0x00528321

0x00528322

0x00528323

0x00528324

0x00528325

0x00528326

0x00528327

0x00528328

0x00528329

0x0052832a

0x0052832b

0x0052832c

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros (apuntadores)

Por tanto, si la dirección de la siguiente posición de memoria disponible es 0x005208320 y los valores de tipo char ocupan 1 byte int ocupan 4 bytes double ocupan 8 bytes

se reservará la memoria de la forma mostrada en el mapa de memoria siguiente.

Ing. Julio César Canelón RangelActualizado: Abril 2007

Mapa de Memoria0x00528320

0x00528321

0x00528322

0x00528323

0x00528324

0x00528325

0x00528326

0x00528327

0x00528328

0x00528329

0x0052832a

0x0052832b

0x0052832c

varInt

varDouble

varChar

int varInt = 1234;double varDouble = 1.2364;char varChar = ‘a’;

int ocupan 4 bytesdouble ocupan 8 byteschar ocupan 1 byte

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros

Se puede obtener la dirección de una variable con el operador de obtención de direccion (&).

&variable es la dirección de la variable Por tanto en el ejemplo anterior, tenemos:

&varInt es 0x005208320 &varDouble es 0x00520324 &varChar es 0x00520832c

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros

Para aprovechar la utilidad de las dirección de memoria, C++ proporciona variables puntero. Una variable puntero (o simplemente puntero) es una variable cuyo valor es una dirección de memoria que apunta a un valor de un tipo de dato específico.

Ing. Julio César Canelón RangelActualizado: Abril 2007

Declaración de punteros

Formas: Tipo *variablePuntero; Tipo *variablePuntero = direccion;DondeTipo es cualquier tipo de dato y direccion es la dirección de un

objeto del Tipo especificado Propósito:

El operador asterisco * debe preceder a cada identificador de tipo puntero.

En la segunda versión, la dirección de inicialización debe ser la de un objeto del mismo tipo que aquel apunta el puntero. (si tipo es entero entonces la dirección debe corresponder a un objeto entero.

Se puede asignar 0 a cualquier variable puntero, es decir dirección nula (NULL).

Ing. Julio César Canelón RangelActualizado: Abril 2007

Ing. Julio César Canelón RangelActualizado: Abril 2007

Ejemplo include <iostream.h> void main () { int i = 11; int j = 22; double d = 3.3; dobule e = 4.4; int *pi, *pj; double *pd, *pe; pi = &i; pj = &j; pd = &d; pe = &e; cout << "&i = " << pi << endl; cout << "&j = " << pj << endl; cout << "&d = " << pd << endl; cout << "&e = " << pe << endl; }

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros

Se podría visualizar el mapa de memoria para el ejercicio anterior de la siguiente manera:

0xbffffd20 11

0xbffffd24 22

0xbffffd30 4.4

0xbffffd28 3.3

0xbffffd20

0xbffffd24

0xbffffd28

0xbffffd30

i

j

d

e

pi

pj

pd

pe

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros

Importante recordar que el operador asterisco * debe preceder a cada variable en una declaración de puntero. Double * pDouble;

Una forma para hacer la innecesaria la utilización del asterisco el la siguiente

Typedef double * PunteroDouble; Después usar el PunteroDouble para declarar los

punteros PunteroDouble pi, pj, pk;

Ing. Julio César Canelón RangelActualizado: Abril 2007

Operaciones Básicas Desreferenciación e indirección: Una variable

puntero almacena sólo la dirección de una posición de memoria. Acceder al contenido de dicha posición de memoria a través del puntero requiere el uso de un operador especial *, denominado operador de desreferenciación. *variablePuntero Esta expresión proporciona acceso a la posición de

memoria cuya dirección está almacenada en variablePuntero, si dicha dirección de memoria ya tiene nombre, podemos considerar *variablePuntero como un alias a dicha posición

Ing. Julio César Canelón RangelActualizado: Abril 2007

Ejemplo

11

0xbffffd20

0xbffffd20

*pi

i

pi

Ing. Julio César Canelón RangelActualizado: Abril 2007

Ejemploinclude <iostream.h> void main () { int i = 11; int j = 22; double d = 3.3; dobule e = 4.4; int *pi, *pj; double *pd, *pe; pi = &i; pj = &j; pd = &d; pe = &e; cout << “\n”En la dirección “ << pi << “, esta almacenado el valor “ << *pi << “\n”; cout << “\n”En la dirección “ << pj << “, esta almacenado el valor “ << *pj << “\n”; cout << “\n”En la dirección “ << pd << “, esta almacenado el valor “ << *pd << “\n”; cout << “\n”En la dirección “ << pe << “, esta almacenado el valor “ << *pe << “\n”;

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros

Con lo anteriormente descrito entonces en base al ejemplo anterior podríamos tener:

int x;

x = *pi + *pj;

cuyo resultado seria x = 33; También podríamos realizar la siguiente

asignación:

*pi = 12;

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros

El operador de indirección puede aplicarse más de una vez para producir niveles adicionales de indirección. int **p;

o también es válido

typedef int PunteroInt;PunteroInt *p

Se declara a p como un puntero a una posición de memoria que contiene a su vez un puntero a otra posición de memoria donde se puede almacenar un int

Ing. Julio César Canelón RangelActualizado: Abril 2007

Puntero descolgado

Se debe tener cuidado antes de desreferenciar un puntero y asegurarse que el puntero no es nulo y apunta a una posición concreta de la memoria, ya que la desferenciación de un puntero nulo o indefinido causa normalmente un error fatal en tiempo de ejecución. Este problema se le conoce como puntero descolgado.

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros Asignación

A las variables puntero se les puede asignar valores de otras variables puntero siempre que este ligadas al mismo tipo de dato.

Ejemplo, si agregáramos la siguiente línea al programa anterior pi = pj;

El valor de pj se copiaría en pi de forma que tendrían la misma dirección de memoria como valor, es decir ambas apuntarían a la misma posición de memoria.

Ing. Julio César Canelón RangelActualizado: Abril 2007

Punteros Comparación

Los operadores relacionales se pueden usar para comparar dos punteros siempre que estén ligados al mismo tipo. Lo más habitual es usar == y != para determinar si dos sectores de memoria. Ejem: pi != pj; pi != null;

No se pueden comparar dos punteros de tipos de datos diferentes. Ejem:

int *pi; double *pd;

if (pi == pd) //expresión no válida

Ing. Julio César Canelón RangelActualizado: Abril 2007

Reserva de memoria dinámica: Operador new Durante la ejecución de un programa se

puede solicitar memoria al sistema operativo usando la operación new. New Tipo.

Donde Tipo puede ser cualquier tipo. Dicha expresión solicita en tiempo de ejecución un bloque de memoria suficientemente grande para almacenar un valor del Tipo especificado

Ing. Julio César Canelón RangelActualizado: Abril 2007

Reserva de memoria dinámica: Operador new Si se puede satisfacer la petición, new

devuelve una dirección la cual puede almacenarse en variables puntero.

Esta operación se utiliza generalmente al lado de un puntero. Ejem:

int * pInt;

pInt = new int;

new int solicita al S.O. un bloque de memoria suficientemente grande para almacenar un valor entero (es decir

(sizeof(int) bytes de memoria). Si el S.O. puede satisfacer la petición, a pInt

se le asiganará la dirección de esa dirección de memoria

0x13eff860

pInt0x13eff860

Ing. Julio César Canelón RangelActualizado: Abril 2007

Reserva de memoria dinámica: Operador new Como no existe un nombre asociado a la nueva

posición de memoria, recibe el nombre de variable anónima; no se puede acceder directamente a ella de la misma manera que se puede acceder al resto de las variables. Sin embargo, su dirección se guarda en pInt por lo que se puede acceder indirectamente a dicha variable anónima desreferenciando pInt, mediante la expresión *pInt.

A la variable anónima se le puede hacer cosa que se puede hacer con una variable “ordinaria”

Ing. Julio César Canelón RangelActualizado: Abril 2007

Parámetros por Referencia

Considerando la siguiente función C++ que intercambia valores entre dos variables enteras.void intercambiar(int &primero, int &segundo)

{

int temp = primero;

primero = segundo;

segundo = temp;

}

Aquí los parámetros están por referencia porque tiene el &.

Entonces para llamar la función dentro de mi programa sería: intercambiar(x, y);

Ing. Julio César Canelón RangelActualizado: Abril 2007

Parámetros por Referencia

Para hacer el mismo efecto pero usando apuntadores sería:void intercambiar(int *primero, int *segundo){

int temp = *primero;*primero = *segundo;*segundo = *primero;

} La función se llamaría en mi programa:

intercambiar(&x, &y);