Está en la página 1de 7

PROGRAMA DE INGENIERIA DE SISTEMAS

GUIA DE LABORATORIO DE ESTRUCTURAS DE DATOS N_03


APUNTADORES Y MEMORIA DINAMICA EN C++

APUNTADORES Ejemplo: El siguiente ejemplo muestra la diferencia entre


una variable tradicional y una de tipo apuntador.
La memoria del computador se encuentra organizada en
grupos de bytes que se denominan palabras. int var1=5;
int *var2;
Dentro de la memoria cada dato ocupa un número var2=&var1;
determinado de bytes:
MEMORIA
Un char  1 byte. POSICION VARIABLE VALOR
Un int  4 bytes. n var1 5 VAR1
n+1 *var2 n
A cada byte o palabra se accede por su dirección. Si x es VAR2
una variable que representa un determinado dato el
.
compilador reservara los bytes necesarios para
.
representar x (4 bytes si es de tipo int).
.
m
La computadora guarda las variables en la memoria y
cada espacio de memoria tiene una dirección.
Como utilizar los apuntadores en C++
Normalmente no necesitamos saber la dirección en la Hay dos operadores muy importantes para la
que está guardada una variable, ya que nos referimos a manipulación de apuntadores: el operador de
ella por su nombre. En C++ existen variables que indirección, que se identifica con el símbolo *
puede guardar una dirección de memoria, se llaman y operador de dirección; que se identifica con
apuntadores. el símbolo &.
El operador de indirección (*) se emplea para
Un apuntador se define como un tipo de dato obtener el valor almacenado en la dirección
capaz de almacenar una dirección de memoria. que guarda la variable apuntador; es decir,
Se considera como referencia indirecta a un accede al contenido y con el se puede realizar
elemento. No todos los lenguajes de programación cualquier operación permitida para este tipo de
permiten el uso de apuntadores. Sus principales valor. Se utiliza de la siguiente forma:
aplicaciones están relacionadas con el manejo de *apuntador;
la memoria dinámica, y en el lenguaje C++ se *objeto.dato;
emplean para permitir el paso de los parámetros objeto dato;
por referencia a los módulos.
La declaración de un apuntador debe realizarse El operador de dirección (&) se utiliza para
antes de usarse y se realiza de la siguiente forma: obtener la dirección de alguna variable. Dicha
Tipo_dato *nombre_apuntador; dirección puede almacenarse en un apuntador
capaz de guardar direcciones del mismo tipo de
int *p; char *c; dato de la variable. Se utiliza de la siguiente
forma:
En este ejemplo, la variable p almacenara
direcciones de elementos enteros, mientras que c &apuntador.
guardara la dirección de valores de carácter.
Nota: El operador de indirección solo se puede
La definición de un apuntador puede incluir emplear con variables apuntador, mientras que el
cualquier tipo de dato primitivo del sistema (int, operador de dirección puede emplearse con
double, char,bool,-) o un dato compuesto (struct, cualquier tipo de variables.
class) definido por programador, por ejemplo:
Un valor muy especial en los punteros es el valor 0
clase_Persona *a; donde a almacenara la (NULL). El valor 0 en los punteros es la indicación
dirección de memoria de cualquier objeto tipo de que no se apunta a nada. Aunque la dirección de
Clase_Persona. memoria 0 existe, no se usa y en punteros es la
indicación básica de que no hay puntero.
int *p;
p = NULL;

DOCENTE: ING. ROGER CALDERON MORENO 1



PROGRAMA DE INGENIERIA DE SISTEMAS
GUIA DE LABORATORIO DE ESTRUCTURAS DE DATOS N_03
APUNTADORES Y MEMORIA DINAMICA EN C++

Ejemplos de Apuntadores: Arreglos

int a, b,*p,*q; int main()


p=&a; a=3; q=p; b=*q+2; {
int var1[5];
var1[0]=0,var1[1]=1,var1[2]=2,var1[3]=3,var1[4]=4;

Lo anterior significa que: int *var2;


var2=var1;
• El apuntador p almacena la dirección de la
variable a. cout<<"Direccion de var1 es "<<&var1<<" Valor de var1"<<*var1<<endl;
• La variable a guarda el valor de 3. //note que no es necesario colocar el operador
//* para conocer un valor determinado del arreglo
• El apuntador q guardara la misma dirección que cout<<"Direccion de var1[0] es "<<&var1[0]<<" Valor de
almacena el apuntador p. var1[0]="<<var1[0]<<endl;
• La variable b toma el contenido apuntado por la cout<<"Direccion de var1[1] es "<<&var1[1]<<" Valor de
var1[1]="<<var1[1]<<endl;
dirección almacenada en q (un 3) y le suma un
cout<<"Direccion de var2 es "<<&var2<<" Valor de var2="<<var2<<endl;
2; por lo tanto b tomara el valor de 5. system("pause");
• Después de estas operaciones, se accesa el return 0;
mismo espacio de memoria con a, *p y *q. }

Otro ejemplo:
int main() Devolver un arreglo de caracteres
{
int var1=5;
int *var2;
char* apuntar(char *dato)
var2=&var1;
{
char *cadena="";
cout<<"Valor de var1 es "<<var1<<" y sus dirección de memoria es
strcpy(cadena,dato);
"<<&var1<<endl;
return cadena;
cout<<"Valor de var2 es "<<var2<<" y sus dirección de memoria es
}
"<<&var2<<endl;
cout<<"Valor apuntado por var2 es "<<*var2<<endl;
int main()
system("pause");
{
return 0;
char *dato="AAA---";
}
char *dato2;
dato2=apuntar(dato);
//cout<<apuntar(dato)<<endl;
Paso de parámetros por referencia con apuntadores cout<<endl<<endl;
cout<<"Valor de dato2 "<<dato2<<endl;
cout<<"Direccion de dato2 "<<&dato2<<endl;
cout<<endl<<endl;
void llenar(int *a) system("pause");
{ return 0;
cout<<endl; }
cout<<"Valor de a es "<<a<<" y sus dirección de memoria es
"<<&a<<endl;
cout<<"Valor apuntado por a es "<<*a<<endl;
}

int main()
{
int var1;
int *var2;

cout<<"Valor de a es "<<var1<<" y sus dirección de memoria es


"<<&var1<<endl;
var1=5;
cout<<"Valor de var1 es "<<var1<<" y sus dirección de memoria es
"<<&var1<<endl;
cout<<"Valor de var2 es "<<var2<<" y sus dirección de memoria es
"<<&var2<<endl;
var2=&var1;
cout<<"Valor de var2 es "<<var2<<" y sus dirección de memoria es
"<<&var2<<endl;
cout<<"Valor apuntado por var2 es "<<*var2<<endl;
llenar(var2);
system("pause");
return 0;
}

DOCENTE: ING. ROGER CALDERON MORENO 2



PROGRAMA DE INGENIERIA DE SISTEMAS
GUIA DE LABORATORIO DE ESTRUCTURAS DE DATOS N_03
APUNTADORES Y MEMORIA DINAMICA EN C++

MEMORIA DINAMICA Ejemplos de memoria dinámica:


double *iva;
iva = new double;
Muchos lenguajes de programación permiten manejar double *salud;
dos tipos de almacenamiento de datos en la memoria salud= new double(12.5);
principal: Estático (automático) y el almacenamiento int *arreglo;
dinámico. arreglo = new int[10];
Mi_clase *p;
La memoria estática es la que se maneja p = new Mi_clase;
tradicionalmente. Sus principales características Mi_clase *q;
son: q = new Mi_clase(10);
delete iva;
• Se define explícitamente al declarar una delete salud;
variable, ya sea global o local. delete [] arreglo;
delete q;
• El compilador genera automáticamente el
delete p;
espacio de memoria.
• Se mantiene fija durante toda la vida de la Manejo de arreglos multidimensionales con
variable(independientemente de que se utilice memoria dinámica:
o no).
La memoria dinámica permite crear y destruir int main()
espacios de memoria, según indicaciones {
int **tabla;
explicitas del programador durante la ejecución del
int n = 10;
programa. Sus principales características son: int m = 10;
int i;
• Utiliza una parte de la memoria principal.
tabla = new int*[n];
• Apoya el uso eficiente de la memoria durante for(i = 0; i < n; i++)
la ejecución. {
• Requiere el uso de apuntadores que tabla[i] = new int[m];
almacenen direcciones de memoria real, dado for (int y=0;y<m;y++)
que estas se asignan dinámicamente. { tabla[i][y] = y;
cout << tabla[i][y] << "\t";
}
En el lenguaje C se cuenta con las operaciones
cout<<"\n";
malloc y free. En C++ se utilizan los operadores }
new y delete. getch();
// Liberar memoria:
for(i = 0; i < n; i++)
Por ejemplo: delete[] tabla[i];
delete[] tabla;
apuntador=new tipo_dato; return 0;
}

La ejecución de new hace una petición al sistema


operativo para que se le otorgue un espacio de
memoria del tamaño asociado al tipo de dato
indicado. Si el espacio de memoria esta
disponible, la operación regresa la dirección del
espacio de memoria que se otorga al
programador, sino hubiera espacio, se regresa el
valor de null. El apuntador toma el valor de la
dirección y apunta a ese nuevo espacio, que
estará separado por el sistema operativo hasta
que sea liberado.

delete apuntador;

La ejecución del delete provoca que se libere el


espacio direccionado por el apuntador, dejándolo
con un valor null.

DOCENTE: ING. ROGER CALDERON MORENO 3



PROGRAMA DE INGENIERIA DE SISTEMAS
GUIA DE LABORATORIO DE ESTRUCTURAS DE DATOS N_03
APUNTADORES Y MEMORIA DINAMICA EN C++

Ejemplo 1:
#include <iostream>
#include <conio>
#define tama 5
class A
{
int a,b,c;
public:
int dato,*apu;
A(){a=b=c=dato=0;}
A(int x)
{
a=b=c=0;a=b=c=x;dato=150;
apu=&a;
}
void mostrar()
{
cout<<a<<" "<<b<<" "<<c<<" "<<b;
}
};
int main()
{
/******************************************
Apuntadores a variables y arreglos
*******************************************/
int arreglo[tama];
int *p,*j;
cout<<"\n\t"<<"Direccion"<<"\t"<<"Valor"<<"\t"<<"Bytes Ocupados"<<"\t"<<endl<<endl;
//ARREGLO SIN INICIALIZAR
for (int i=0;i<=tama;i++)
cout<<"\t"<<&arreglo[i]<<"\t"<<arreglo[i]<<"\t"<<"\t"<<sizeof(arreglo[i])<<endl;
cout<<endl<<endl;
//ARREGLO SIN INICIALIZADO
for (int i=0;i<=tama;i++)
{
arreglo[i]=i;
cout<<"\t"<<&arreglo[i]<<"\t"<<arreglo[i]<<"\t"<<"\t"<<sizeof(arreglo[i])<<endl;
}
cout<<endl<<endl;
p=arreglo;
cout<<"\t"<<"Direccion de p "<<&p<<endl;
cout<<"\t"<<"Valor de p "<<p<<endl;
cout<<"\t"<<"Valor por indireccion p "<<*p<<endl;
cout<<endl<<endl;
j=p;
cout<<"\t"<<"Direccion de j "<<&j<<endl;
cout<<"\t"<<"Valor de j "<<j<<endl;
cout<<"\t"<<"Valor por indireccion j "<<*j<<endl;
cout<<endl<<endl;

/*****************************************
Apuntadores a Objetos
*******************************************/
A *q;
A ob(5);
cout<<"\n\t"<<"Direccion de memoria del objeto ob "<<&ob;
cout<<"\n\t"<<"Valores desde el Objeto ";ob.mostrar();
cout<<"\n\t"<<"Valor de la variable dato desde el objeto = "<<ob.dato;
cout<<"\n\t"<<"Valor de la variable apu "<<*ob.apu;
cout<<endl<<endl;
q=&ob;
cout<<"\n\t"<<"Direccion de memoria del apuntador q "<<&q;
cout<<"\n\t"<<"Valor de q "<<q;
cout<<"\n\t"<<"Valores desde el apuntador q al objeto ob ";q->mostrar();
cout<<"\n\t"<<"Valor de la variable dato desde el apuntador q = "<<q->dato;
cout<<"\n\t"<<"Valor de la variable apu "<<*q->apu;
q=NULL;
cout<<"\n\t"<<"Direccion de memoria del apuntador q al asignarle NULL "<<&q;
cout<<"\n\t"<<"Nuevo valor de q "<<q;
getch();
return 0;
}

DOCENTE: ING. ROGER CALDERON MORENO 4



PROGRAMA DE INGENIERIA DE SISTEMAS
GUIA DE LABORATORIO DE ESTRUCTURAS DE DATOS N_03
APUNTADORES Y MEMORIA DINAMICA EN C++

Ejemplo 2:
#include <conio>
#include <iostream>

class A
{
int a,b,c;
public:
static int tot=0;
A(){a=b=c=0;tot++;cout<<"\n"<<"objeto creado # "<<ob_creados();}
A(int x)
{
a=b=c=0;
a=b=c=x;
tot++;
cout<<"\n"<<"objetos creado # "<<ob_creados();
}
void mostrar()
{
cout<<"\n"<<a<<" "<<b<<" "<<c<<" "<<b;
}
int ob_creados()
{
return tot;
}
~A()
{
cout<<"\n"<<"Se elimino un objeto "<<tot;
tot--;
}
};

class B
{
char x,*y;
public:
static int tot=0;
B()
{
x='0';
y= new char[5];
tot++;
}
void mostrar()
{
y[0]='1';
y[1]='2';
y[2]='3';
y[3]='4';
y[4]='5';
cout<<"\n"<<y[0]<<" "<<y[1]<<" "<<y[2]<<" "<<y[3]<<" "<<y[4];
cout<<"\n"<<"Valor del atributo x es "<<x;
}
int ob_creados()
{
return tot;
}
~B()
{
delete y;
cout<<"\n"<<"Se elimino un objeto # "<<ob_creados();
tot--;
}
};

int main()
{
cout<<"\n\t\t"<<"Clase A \n";
A obj1;
obj1.mostrar();
getch();
A *ap1;//Creo un apuntador de tipo A
ap1=new A(5);//asigno memoria dinamica al apuntador creado e inicializo el objeto
ap1->mostrar();
getch();

DOCENTE: ING. ROGER CALDERON MORENO 5



PROGRAMA DE INGENIERIA DE SISTEMAS
GUIA DE LABORATORIO DE ESTRUCTURAS DE DATOS N_03
APUNTADORES Y MEMORIA DINAMICA EN C++

A *ap2;//Creo un apuntador de tipo A


ap2=ap1;
ap2->mostrar();//as
getch();
ap1=&obj1;
ap1->mostrar();
getch();
ap1=NULL; //ASIGNAMOS UN DIRECCION NULA AL APUNTADOR PARA ELEMINARLO
//////////////////////////////////////////////////////////////////////////////
cout<<"\n\t\t"<<"Arreglo de Objetos \n";
A re[5]; //arreglo de objetos, todos los obj quedan inicializados

re[0].mostrar();
re[1].mostrar();
re[2].mostrar();
re[3].mostrar();
re[4].mostrar();

A *arre;
arre=new A[5]; //arreglo de apuntadores dinámicos a objetos
arre[0].mostrar();
arre[1].mostrar();
arre[2].mostrar();
arre[3].mostrar();
arre[4].mostrar();
getch();
cout<<"\n\t\t"<<"Eliminar Objetos \n";
delete []arre; //liberar memoria
re[0].~A();
re[1].~A();
re[2].~A();
re[3].~A();
re[4].~A();
//////////////////////////////////////////////////////////////////////////////
delete ap1;
delete ap2;
obj1.~A();
getch();
getch();
getch();
clrscr();
cout<<"\n\t\t"<<"Clase B \n";
B obj22;
obj22.mostrar();
B obj33;
obj33.mostrar();
getch();
obj33.~B();
obj22.~B();
getch();
return 0;
}

DOCENTE: ING. ROGER CALDERON MORENO 6



PROGRAMA DE INGENIERIA DE SISTEMAS
GUIA DE LABORATORIO DE ESTRUCTURAS DE DATOS N_03
APUNTADORES Y MEMORIA DINAMICA EN C++

Taller 3.
1 – Realice los ejercicios de ejemplo propuestos en la guía.
2 - Diseñar y codificar una clase en C++ que permita crear conjuntos de tamaño variable de tipo enteros positivos
mayores a cero, donde el usuario debe suministrar el tamaño de los conjuntos, el valor del tamaño del conjunto se debe
recibir en el constructor de la clase, además el conjunto se debe poder llenar de forma aleatoria o de forma manual, eso lo
define el usuario. La clase debe tener como mínimo los siguientes métodos y atributos:

Método Parámetro Parámetro Descripción


Recibe Salida
miclase int --- Constructor de la clase
cantidadElementos --- int Indica el tamaño del arreglo
lleanarAleatoriamente --- --- Llena de forma aleatoria el arreglo
lleanarManual --- --- Llena de forma manual el arreglo

Atributo Tipo Tamaño Descripción


miconjunto int n Atributo de la clase que contiene el conjunto generado
(arreglo dinamico) y el cual es de tamaño variable.

Diseñe y codifique una clase en C++ que permita realizar operaciones sobre conjunto de datos (objetos de la clase
conjuntos). La clase debe implementar los siguientes métodos:

Método Parámetro Recibe Parámetro Descripción


Salida
union Conjunto1 y --- Une los dos conjuntos en un nuevo conjunto y lo
Conjunto2 imprime.
interseccion Conjunto1 y --- Intersección de los dos conjunto, donde el resultado
Conjunto2 es un nuevo conjunto y lo imprime.
diferencia Conjunto1 y --- Diferencia de los dos conjunto, donde el resultado es
Conjunto2 un nuevo conjunto y lo imprime.
iguales Conjunto1 y bolean Verifica que los dos conjuntos sean iguales
Conjunto2
diferentes Conjunto1 y bolean Verifica que los dos conjuntos sean diferentes
Conjunto2
subconjunto Conjunto1 y --- Crean un subconjunto del conjunto que recibe, el
int n tamaño del subconjunto es n.
suma Conjunto int Suma los datos del conjunto que recibe.
promedio Conjunto double Promedio de los datos del conjunto que recibe.
varianza Conjunto double Varianza de los datos del conjunto que recibe.
desviacion Conjunto double Desviación de los datos del conjunto que recibe.
imprimir Conjunto --- Imprime en pantalla los datos del conjunto que recibe.

Varianza Promedio

Desviación
Estándar

DOCENTE: ING. ROGER CALDERON MORENO 7




También podría gustarte