Está en la página 1de 16

Tema 6.

Punteros y Gestión de
memoria dinámica

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 1 / 16


Objetivos
• Conocer la organización de la memoria
• Conocer y saber utilizar el tipo Puntero en C++:
declaración de variables y manejo de operadores
• Comprender el concepto de referencia en C++, su
relación con el tipo puntero y saber utilizarlas.
• Saber utilizar el tipo puntero y las referencias para
realizar el paso de parámetros por variable de tipos
simples y tipos estructurados
• Conocer la relación entre vectores de elementos y el
tipo puntero
• Saber reservar y liberar memoria dinámica en C++

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 2 / 16


Uso de la memoria
• La memoria de un ordenador está dividida en casillas o celdas de
igual tamaño
• Para acceder a una casilla determinada hay que señalar su
dirección, que identifica unívocamente a cada casilla
• Cuando se desea ejecutar un programa, el sistema operativo lo
carga en memoria realizando una asignación de espacio similar a la
siguiente:
Zona de código
Datos estáticos
Zona de datos

Montículo (Heap)

Datos dinámicos
Memoria sin asignar

Pila (Stack)

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 3 / 16


Zona de memoria para un programa
• Zona de código, donde se almacena el código máquina del
ejecutable
• Zona de datos, donde se reserva espacio para almacenar las
variables globales, constantes globales, etc. Su tamaño se define en
tiempo de compilación
• Pila (Stack)
– Almacena la información de retorno de las funciones, sus parámetros y sus
variables locales
– Aumenta o disminuye conforme se van ejecutando o finalizando las
funciones
– Su tamaño máximo se define en tiempo de compilación
– Si programamos en un lenguaje de alto nivel se gestiona automáticamente
• Montículo (Heap o "memoria dinámica")
– Memoria que el programador solicita en tiempo de ejecución
– Es gestionada por el programador reservando y liberando bloques de
memoria

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 4 / 16


Tipo puntero
• Un puntero a un tipo de dato T es una dirección de
memoria donde se almacena un dato de tipo T
• Sintaxis para definir una variable de tipo puntero:
<TIPO_apuntado > *<identificador_variable>;
• Ejemplos:
– int *pdato;
– Tpersona *persona;
• Mecanismo utilizado para el paso de parámetros por
referencia o variable y para referenciar bloques de
memoria en el Heap
– Su correcto uso es crítico para una buena programación
– Su uso inadecuado puede ocasionar errores difíciles de detectar

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 5 / 16


Tipo puntero
• Operador de dirección o referencia (&): se aplica a una
variable o a un objeto (elemento de un vector o estructura) y
devuelve la dirección de memoria donde se almacena
• Operador de indirección o desreferencia (*): se aplica a una
variable tipo puntero y devuelve la variable u objeto apuntado

int valor=20; 1016

int *p=&valor; 1012

cout << *p; //Muestra 20 1008


p 1000
*p = 15;
1004
cout << valor; //Muestra 15 valor 20
15
1000

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 6 / 16


Tipo puntero
• Cuando se declara una variable de tipo puntero
tendrá un valor no definido que habrá que inicializar
int *pvalor;
• En C++ se utiliza el valor 0 para identificar una
dirección de memoria que no apunta a ningún objeto
int *pvalor=0; // puntero nulo
El literal 0 se convierte
implícitamente a una dirección de
memoria en la que no está
almacenado ningún objeto

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 7 / 16


Punteros a estructuras
• Acceso a los campos de un registro:
(*puntero).campo o puntero->campo

struct Tpersona {
string nombre;
int dni;
};
….
Tpersona alumno;
alumno.nombre =“Juan”; alumno.dni = 23456784;
Tpersona *palumno = &alumno;
cout << (*palumno).nombre;
cout << palumno->nombre;

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 8 / 16


Paso de parámetros por variable o referencia
• El tipo puntero también es usado en para el paso de
parámetros por variable o referencia
void Factorial (int n, int &f) { void Factorial (int n, int *f) {
int i; int i;
f = 1; *f = 1;
for (i = 2; i <= n; i++) for (i = 2; i <= n; i++)
f = f * i; *f = (*f) * i;
} }

int res; int res;


Factorial(4,res); Factorial(4, &res);
cout << res; cout << res;

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 9 / 16


Aritmética de punteros
• Si tenemos
T *p;
entonces p+e (e de tipo entero), produce un valor
de tipo puntero a un dato de tipo T y de valor
p+e*sizeof(T)

• Ejemplo:
int *p=…; //suponemos que toma la dirección 1000
p=p+2; //ahora p vale 1008 , si sizeof(int) es 4

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 10 / 16


Arrays y punteros
• Una variable de tipo array almacena realmente un puntero a
la dirección de memoria del primer elemento
1016
int v[] = {32,45,87,23}; 23
int *p = v; 1012
87
1008
*(p+i) es equivalente a v[i] 45
1004
Los punteros y los arrays están
32
íntimamente relacionados y es 1000
posible aplicar el operador [] a v
un puntero p

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 11 / 16


Arrays y punteros
• El identificador de un array es realmente un puntero
a la dirección de memoria del primer elemento
1016
int v[] = {32,45,87,23}; 23
int *p,*q; 1012
p = v; //asignamos el valor 1000 ?
87
16
1008
cout << p[1]; //Muestra 45 45
p[2] = 16; qq 1004
cout << v[2]; // Muestra 16 32
q = &v[2]; 1000
v
cout << *q; // Muestra 16 p
cout << q[0]; // Muestra 16
cout << q[1]; // Muestra 23

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 12 / 16


Paso de parámetros de tipo vector
• En C++ los vectores siempre se pasan por referencia
• Se puede utilizar indistintamente la sintaxis de vector
como la de puntero para expresar los parámetros
formales:
void Duplica (int v[ ], int tam) { int valores[] = {1, 2, 3, 4, 5};
for (int i = 0; i < tam; i++)
v[i]*=2; Duplica(valores, 5);
} Visualiza(valores, 5); //2,4,6,8,10
void Visualiza (const int *v, int tam) {
for (int i = 0; i < tam; i++) Duplica(&valores[2], 2);
cout << v[i] << ' '; Visualiza(valores, 5); //2,4,12,16,10
}

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 13 / 16


Gestión de memoria dinámica (heap)
• Uso de la memoria dinámica en tiempo de ejecución
• Procedimiento: solicitar un bloque de memoria del heap que pueda
almacenar nuestro/s dato/s y guardar su dirección de memoria en
una variable de tipo puntero
– Operador new: reserva un bloque de memoria para almacenar un/os
valor/es de un tipo de valor y devuelve su dirección de inicio
• Sintaxis básica:
TIPO *puntero = new TIPO;
//reserva una zona para almacenar un valor de ese tipo
TIPO *puntero = new TIPO[tam];
//reserva tam zonas contiguas de memoria
– Operador delete: libera un bloque de memoria dada su dirección para
que pueda utilizarse en otra parte del programa
• Sintaxis básica:
Errores:
delete puntero; Al hacer new si no hay espacio suficiente
delete[] puntero; Hacer delete sobre una dirección no
devuelta mediante new

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 14 / 16


Gestión de memoria dinámica
int *pvalor = 0;
*pvalor = 25; //error: memoria no reservada

pvalor = new int; //Se reserva un bloque para almacenar un entero


*pvalor = 25;

delete pvalor; //No debemos olvidar liberar cuando no vaya a utilizarse

int tam;
int *valores = 0;
cout << "Cuántos datos quieres introducir?";
cin >> tam;
valores = new int[tam]; //Se reserva un bloque para tam enteros
//trabajamos con el vector valores de tamaño tam

delete [ ] valores; //Se libera el bloque de memoria

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 15 / 16


RESUMEN
• Un programa en ejecución tiene asignada una zona
de memoria estática, pero también puede hacer uso
de la memoria dinámica.
• Un puntero es un tipo de dato que almacena una
dirección de memoria en la que se aloja un dato.
• Los operadores de dirección (&) e indirección (*)
permiten trabajar con punteros.
• Las instrucciones new y delete permiten utilizar
memoria dinámica para almacenar (grandes)
conjuntos de datos.

Fundamentos de Programación Tema 6. Punteros y gestión de memoria dinámica 16 / 16

También podría gustarte