3. Punteros y referenciasx

Download Report

Transcript 3. Punteros y referenciasx

Informática II
Diego Fernando Serna Restrepo
1
Semestre 2011/2
Chiste del Día
Informática II
2011/2
2
Contenido
1
Qué son punteros
2
Cómo declarar y usar punteros?
3
Free store - Stack
4
Cómo manipular la memoria
Informática II
2011/2
3
• Es un tipo de variable implementada para
almacenar exclusivamente direcciones de otras
variables, estos se debe declarar y definir de
acuerdo al tipo de dato que apunta.
Utilizando punteros un programa puede realizar
muchas tareas que no sería posible utilizando tipos
de datos estándar.
Informática II
2011/2
4
Características de un apuntador
• Un puntero es una variable como cualquier otra.
Excepto que solo puede almacenar direcciones de
otras variables común y corrientes.
• Un puntero apunta a una variable en memoria.
• Son útiles para pasar y regresar valores a la rutina que
las llama.
• Si son usadas incorrectamente se pueden convertir en
fuente de fallas y frustraciones.
El tipo de variable que
almacena una dirección
se denomina puntero.
Informática II
2011/2
Punteros
Los punteros siempre deben inicializarse.
Aquellos punteros que son inicializados con un valor igual a
cero (0), se denominan punteros NULL.
Se utiliza la palabra reservada VOID en la declaración de
apuntadores, cuando se quiere que el puntero pueda
apuntar a cualquier tipo de variables, int , char, float,….
Aquellos punteros que no sean inicializados a ningún valor
se denominan “wild pointer”, y son extremadamente
peligrosos pues pueden estar apuntando a cualquier cosa.
Informática II
2011/2
6
Violación de seguridad de la memoria
“Dangling
pointer”
“Wild
pointer”
Un objeto apuntado se
suprime sin modificar el
puntero
Se crea un puntero y se usa
antes de la inicialización
Si se reasigna ese espacio
libre en memoria, el puntero
referenciará la nueva
variable (allocate),.
El puntero puede estar
apuntado a cualquier
posición desconocida de
memoria
Generan corrupción de datos y posiblemente fallos de segmentación.
Informática II
2011/2
7
¿Para que se usan los
punteros?
Ж
Ж
Ж
Ж
Ж
• Manipular datos en el Free store (Heap).
• Acceder a las variables miembro y métodos de un objeto.
• Pasar variables por referencia a las funciones
• Gestionar y administrar datos en memoria.
• El utilizar punteros como valor de retorno permite superar
la limitación de las funciones de devolver un único valor.
Informática II
2011/2
8
Contenido
1
Qué son punteros
2
Cómo declarar y usar punteros?
3
Free store - Stack
4
Cómo manipular la memoria
Informática II
2011/2
9
Variables y memoria
Apuntadores
Cuando se declara una variable en C++, el
compilador establece un área de memoria para
almacenar el contenido de la variable. Esa
variable se sitúa en una posición específica de
la memoria, conocida como dirección de memoria.
1000
1001
int y=25;
1002
y
25
1003
int z=77;
1004
z
1005
77
Se utilizan los
apuntadores para
optimizar el acceso a
esas variables.
Un puntero en C++ es
una Variable que SOLO
guarda la dirección de
memoria de otra
variable.
Informática II
2011/2
MEMORIA
Variables y memoria
#include <iostream>
using namespace std;
void main()
{
int y = 25;
int z=77;
cout << " y= " << y << endl;
/ * visualiza el valor de y * /
cout << " Dir y= " << &y << endl; / * visualiza dirección de y * /
}
1000
y = 25
1001
&y = 1002
1002
y
25
1003
1004
z
77
1005
Informática II
2011/2
Declaración de Apuntadores
Apuntadores
Como cualquier variable, las variables punteros
han de ser declaradas antes de utilizarlas. Se
utiliza asterisco (*) para indicar que la variable es
variable apuntador.
Ejemplos:
int *ptr1;
// Puntero a un tipo de dato entero (int)
char *ptr2; / * Puntero a un tipo de dato char * /
float *f; / * Puntero a un tipo de dato float * /
SIEMPRE que aparezca un asterisco ( * ) en una
definición de una variable, ésta es una variable
puntero.
Informática II
2011/2
Inicialización de Apuntadores
Apuntadores
El operador '&', permite conocer la dirección en
memoria de una variable.
&vble;
Los punteros pueden trabajar con esas
direcciones.
Cout << " y= " << y<< endl;
0x5010
0x5011
0x5012
y
0x5013
0x5014
0x5015
53
cout << " &y= " << &y<<endl;
Apuntadores
Inicialización de Apuntadores
int i;
int *ptr;
ptr=&i;
/* define una variable i */
/* define un puntero a un entero ptr*/
/* Almacene la dirección de i en ptr */
Se puede acceder al valor de i por medio
del apuntador ptr.
void main() {
int var1;
int i=3;
int *ptr;
ptr = &i;
0x5020
var1
3
4
i
3
4
0x5021
0x5022
0x5023
0x5024
……..
var1=*ptr;
var1++;
*ptr=var1;
}
0x8090
ptr
Informática II
2011/2
0x5022
Ejemplo Apuntadores
• unsigned short int edad = 50; // creación de
variable
• unsigned short int * pEdad = 0; // creación de
//puntero.
• pEdad = &edad;
// asignando la dirección de edad en pEdad.
• cout << pEdad;
// imprimiendo la dirección guardada en pEdad.
• cout << *pEdad;
// imprimiento el valor al que apunta el puntero.
Informática II
2011/2
15
Ejemplo Apuntadores
#include <archivo_cabecera>
int main() {
int i,j;
int *p;
p = &i;
*p = 5;
j = i;
return 0;
}
Informática II
2011/2
16
Operadores con Apuntadores
OPERADORES
Obtiene la dirección de una variable.
Define una variable como puntero.
Obtiene el contenido de una variable puntero.
C++ requiere que las variables puntero
direccionen realmente variables del mismo tipo
de dato que está ligado a los punteros en sus
declaraciones.
Informática II
2011/2
Punteros a Punteros
PUNTEROS A PUNTEROS
Un puntero puede apuntar a otra variable puntero.
Este concepto se utiliza con mucha frecuencia en
programas complejos de C++.
Se hace uso del operador * dos veces
Ejemplo: Declaremos una variable tipo carácter, también un apuntador a esta variable.
Y luego declaremos un puntero que apunte a este ultimo puntero.
char letra = ´A´;
char *ptr1 = &letra;
char **ptr2 = &ptr1;
Para acceder al contenido de letra se puede hacer por
medio de:
La misma variable
El apuntador ptr1
El apuntador ptr2
Informática II 2011/2
Aritmética de punteros
ARITMETICA DE PUNTEROS
Es muy útil hacer que un puntero apunte a un
elemento en memoria que este antes o después del
dato originalmente apuntado.
dato1
34
dato2
21
dato3
18
….
ptr
Si dato1,2 y 3 estan en posiciones contiguas
de memoria, se puede recorrer todas estas
posiciones con un apuntador, realizando la
suma o la resta a este puntero (dirección de
memoria).
int dato1=34,dato2=21,dato3=18;
int *ptr=&dato1;
ptr=ptr+1; //Queda apuntando a dato2
ptr++;
//Queda apuntando a dato3
ptr--;
//Apunta de nuevo a dato2
Informática II
2011/2
Apuntadores y arreglos
PUNTEROS Y ARREGLOS
En C++ se pueden direccionar arreglos como si fueran
punteros y viceversa
int arreglo[4] = {2, 3, 10, 8};
int *ptrArr;
arreglo[0]
6050
2
*ptrArr
ptrArr
3
*(ptrArr+1)
ptrArr+1
arreglo
ptrArr=&arreglo[0];
arreglo[1]
6052
arreglo[2]
6054
arreglo[3]
6056
10
8
*(ptrArr+2)
ptrArr+2
*(ptrArr+3)
ptrArr+3
6058
……
6050
ptrArr
Informática II
2011/2
PUNTEROS Y ARREGLOS
Arreglo de punteros
Un arreglo de caracteres es una colección de variables
tipo caracter
Un arreglo de punteros es …….
int *arrPtr[7];
arrEnt[0]
12
arrPtr[0]
&var1
arrEnt[1]
32
arrPtr[1]
&var2
arrEnt[2]
7
arrPtr[2]
&var1
arrPtr[3]
&var3
….
arrPtr[4]
&varX
arrPtr[0]
&var1
arrPtr[5]
NULL
arrPtr[1]
&var2
arrPtr[6]
&varX
arrPtr[2]
&var1
arrPtr[3]
&var3
Informática II
2011/2
Contenido
1
Qué son punteros
2
Cómo declarar y usar punteros?
3
Free store - Stack
4
Cómo manipular la memoria
Informática II
2011/2
23
Modo de almacenamiento
•
El modo de almacenamiento (storage class) es otra característica de las
variables de C++ que determina cuándo se crea una variable, cuándo
deja de existir y desde dónde se puede acceder a ella.
Auto
• Es creada al comenzar a ejecutarse un bloque de código y deja de
existir cuando el bloque se termina de ejecutar. (Por defecto)
Extern
• Estas variables existen durante toda la ejecución del programa.
Una variable extern es definida o creada el momento en el que se
le reserva memoria.
• permiten transmitir valores entre distintas funciones y ficheros
Static
• static se declaran dentro de un bloque como las auto, pero
permanecen en memoria durante toda la ejecución del programa
como las extern. La inicialización sólo se realiza la primera vez.
Register
• Este modo es una recomendación para el compilador, con objeto
de que si es posible ciertas variables sean almacenadas en los
registros de la CPU y los cálculos con ellas sean más rápidos.
Informática II
2011/2
24
Espacios de memoria
Segmento de código
Memoria estática
Free store (Heap)
Espacio Libre
Stack (Pila)
Informática II
Es
unazona
zonade
de memoria
memoria
Es una
Reservada
antes
de la
que
gestiona
lasprograma
llamadas
ejecución
donde
se reservan
del
y se a
funciones
durante
la
Permanece
liberan
“trozos”
fija.
durante
la
ejecución
de
programa.
No requiere
ejecución
deun
los
gestión
Cada vez que se realiza
durante la ejecución.
programas
según sus
una llamada a una función
El sistema
propias
necesidades,
operativoeste
se
en el programa, se crea un
encarga
proceso
es
deprograma
usualmente
la reserva,
entorno de
que se
recuperación
llamado
gestión
y desu
libera cuando
acaba
reutilización.
memoria
ejecución. dinámica.
Se
accedeyaliberación
un espacio
La reserva
de
Optimiza
elrealiza
enmemoria
esta cada
vez que
se
la
la
el S.O.
almacenamiento
de
de
forma automática
declaran
Variables
durante
del
datos.
globaleslaoejecución
tipo static.
programa.
2009/2
25
“Free store” – “Heap”
• El Free Store es un espacio de memoria
muy grande, donde es posible
almacenar información; solo puede ser
manipulado por medio de punteros.
• A diferencia que en el Stack, la memoria
reservada en el Free Store no se libera
sino hasta que se termina el programa o
es liberada manualmente.
• TIP: Usualmente se usan los
destructores para liberar la memoria
Informática II
2011/2
26
“Free store” – “Heap”
• Para reservar memoria en el Heap es
necesario usar el comando new, el cual
devuelve la dirección donde se reservó
la variable.
typedef unsigned short int USHORT;
USHORT * pPuntero;
pPuntero = new USHORT;
/*también es posible hacerlo todo en una
sola línea.
USHORT * pPuntero = new USHORT; */
Informática II
2011/2
27
Gestión dinámica de memoria
1. Petición al S.O.
(tamaño)
2. El S.O. comprueba si
hay suficiente espacio
libre.
3. Si hay espacio
suficiente, devuelve la
ubicación donde se
encuentra la memoria
reservada, y marca
dicha zona como
memoria ocupada.
Informática II
2011/2
28
Gestión dinámica de memoria
4. La ubicación de la zona
de memoria se almacena
en una variable estática
(p1) o en una variable
automática (p2).
Nota: Si la petición
devuelve una dirección de
memoria, p1 y p2 deben ser
variables de tipo puntero al
tipo de dato que se ha
reservado.
Informática II
2011/2
29
Gestión dinámica de memoria
5. A su vez, es posible
que las nuevas
variables dinámicas
creadas puedan
almacenar la dirección
de nuevas peticiones
de reserva de memoria.
Informática II
2011/2
30
Gestión dinámica de memoria
6. Una vez que se han
utilizado las variables
dinámicas y ya no se
van a necesitar más es
necesario liberar la
memoria que se está
utilizando e informar al
S.O. que esta zona de
memoria vuelve a estar
libre para su utilización.
Informática II
2011/2
31
Gestión dinámica de memoria
Informática II
2011/2
32
Contenido
1
Qué son punteros
2
Cómo declarar y usar punteros?
3
Free store - Stack
4
Cómo manipular la memoria
Informática II
2011/2
33
Operador new
• Un operador que reserva la cantidad de
memoria deseada en tiempo de ejecución.
new reserva una zona de memoria en el Heap del tamaño adecuado
para almacenar un dato de cualquier tipo, devolviendo la dirección
de memoria donde empieza la zona reservada.
Si new no puede reservar espacio (Ej. no hay suficiente memoria
disponible), se provoca una excepción y el programa termina.
La única forma de crear, modificar, acceder o eliminar una variable
en el Heap es a través de un puntero.
Se puede gestionar memoria para almacenar variables de tipo
predefinido (int, float, double, …) al igual que los tipos de datos
creados por el usuario (estructuras, clases…).
Informática II
2011/2
34
Liberando la memoria del heap
• Para liberar la memoria del HEAP se usa
el comando delete sobre el puntero.
delete pPuntero;
• Es MUY importante liberar la memoria
del Heap, pues en caso de perder el
rastro de los punteros podrán presentarse
“fugas de memoria”
Informática II
2011/2
35
Operador delete
• El operador delete no elimina el puntero,
simplemente lo desreferencia.
int *ptr =new int; //reserva memoria
delete
ptr;se utiliza//desreferncia
ptrmás
• Cuando
el operardo delete
ptr=NULL;
//lo lleva a NULL
de una vez, puede
generar que el
delete ptr;
//no hay problema
programa se estrelle, por ello es
//se puede volver a referenciar a otro
recomendable
inicializar el puntero a
espacio
de memoria
NULL,
haciendo esto se garantiza mayor
ptr=new
int;
seguridad, y de este modo se puede
volver a reutilizar el puntero.
Informática II
2011/2
36
Fugas de memoria
• Cuando “se pierde de vista” la dirección o
el puntero que lleva registro del espacio
en el Heap, se dice que hubo una fuga de
memoria.
• La memoria desperdiciada por causa de
fugas de memoria, NO podrá liberarse
sino hasta que termine el programa.
Informática II
2009/2
37
Fugas de memoria
• Es muy frecuente que ocurra cuando el puntero
es declarado como variable local (dentro de una
función) y luego se sale de ésta sin antes liberar
la memoria.
• Es muy común usar los constructores para
reservar memoria en el heap y los destructores
para liberarla.
• ¡OJO!, realizar un delete sobre un puntero libera
la memoria, realizarlo de nuevo estrellará el
programa. Para que esto no ocurra, asígnele al
puntero el valor de cero DESPUÉS de hacer el
primer delete.
Informática II
2009/2
38
Uso de objetos en el free store
• La asignación de un objeto en el Heap es
igual que la asignación de cualquier otro
tipo
Gato * pPelusa = new Gato;
/*Este comando creará un objeto tipo Gato
en el Heap, llamando su contructor*/
Informática II
2009/2
39
Accediendo a los miembros
de una clase
• //Las siguientes lineas hacen lo mismo
(* pCat).numeroPatas();
pCat->numeroPatas();
Informática II
2009/2
40
Apuntadores como datos
miembro
• Todas las variables pueden ser
declaradas para que habiten en el Heap,
incluso las variables miembro de los
objetos.
Informática II
2009/2
41
El Puntero “this”
• Todas las clases tienen un puntero
escondido denominado “this”, el cual
apunta sobre la dirección del objeto en
cuestión.
• No hay necesidad de preocuparse de la
creación ni el borrado de este puntero,
pues el compilador se encarga de esto.
Informática II
2009/2
42
Uso de punteros constantes
• const int * pUno; // El valor al que apunta pUno
//no puede ser modificado
• int * const pDos; // El valor de dirección no
// puede ser modificada
• const int * const pTres; // ni el valor de la
// dirección, ni el valor al que apunta
// pTres puede ser modificado
Informática II
2009/2
43
Uso de punteros constantes
• Cuando un puntero es declarado para que
apunte a un objeto constante, solo podrá
acceder a los métodos constantes de
dicho objeto.
• El puntero this de un objeto constante solo
podrá ser usado con métodos constantes.
Informática II
2009/2
44
Zona de Preguntas
<iostream>
1.#include
Cómo
se declara un puntero?
double *ptr;
//el puntero
se
declara como global
main()
2.intPara
que son útiles los punteros?
{
for(;;){
//bucle infinito
ptr=new double;
//se pide espacio
en la memoria dinámica
}
4. Cómo
se 0;
reserva memoria en el heap?
return
}
3. Que es el heap o free store?
5. Mencione 2 caracteristicas del heap
6. Que pasa en el código mostrado?
Informática II
2009/2
45
Resumen de apuntadores
Expresión
Lectura
*x
&x
x.y
Apuntado por x
Dirección de x
Miembro y del objeto x
x->y
Miembro y del objeto apuntado
por x
Miembro y del objeto apuntado
por x
(*x).y
x[0]
x[1]
x[n+1]
Primer objeto apuntado por x
Segundo objeto apuntado por x
Objeto (n+1) apuntado por x
Informática II
2009/2
46
Informática II
2009/2
47
Bibliografía
• man, ¡no dude en utilizarlo!!
• Como Programar en C++ - Deithel &
Deithel Ed. PRENTICE HALL
• Sams Teach Yourself C++ in One Hour a
Day, J. Liberty,S. Rao, B. Jones
http://newdata.box.sk/bx/c/
Informática II
2011/2
48
49
Informática II