estructura de datos

Page 1

ESTRUCTURA DE DATOS I UFT

HECHO POR: MAYRA RODRIGUEZ Y MARIA FERNANDA MANRIQUE


Esta revista esta creada para todo aquel interesado en saber algo de programación principalmente esta basada en la memoria dinámica y en los punteros, su utilización, los componentes necesarios para crearlos y algunos ejemplos de punteros y de la memoria dinámica. La memoria dinámica, más que un tipo de memoria es una manera de utilizarla. Consiste en declarar variables y eliminarlas cuando ya no sean necesarias, mediante subprogramas. La memoria dinámica es un espacio de almacenamiento que se puede solicitar en tiempo de ejecución.


Hasta ahora, hemos realizado una administración de memoria de tipo estático. Esto significa que los vectores y matrices creados tienen un tamaño fijo que el compilador conoce en tiempo de compilación. Sin embargo, es posible que el tamaño de dichos vectores no se conozca a-priori y por lo tanto necesitemos solicitar memoria al sistema en tiempo de ejecución. La administración de memoria desde este punto de vista recibe el nombre de memoria dinámica. La memoria dinámica, más que un tipo de memoria es una en declarar variables y eliminarlas cuando ya no sean necesarias, mediante subprogramas. La memoria dinámica es un espacio de almacenamiento que se puede solicitar en tiempo de ejecución. Además de solicitar espacios de almacenamiento, también podemos liberarlos (en tiempo de ejecución) cuando dejemos de necesitarlos. Manejo de la memoria dinámica

La memoria dinámica es un espacio de almacenamiento que manera de utilizarla. Consiste se solicita en tiempo de ejecución. De esa manera, a medida que el proceso va necesitando espacio para más líneas, va solicitando más memoria al sistema operativo para guardarlas. El medio para manejar la memoria que otorga el sistema operativo, es el puntero, puesto que no podemos saber en tiempo de compilación dónde nos dará huecos el sistema operativo (en la memoria de nuestro PC).


Además de solicitar espacios de almacenamiento, también podemos liberarlos (en tiempo de ejecución) cuando dejemos de necesitarlos. Para realizar esta administración de la memoria dinámica, C++ cuenta con dos operadores new y delete. Antes de utilizarlos, debemos incluir el encabezado <new>. El operador new reserva memoria dinámica de cualquier tipo, esto es: • tipos primitivos (int, double, etc) • tipos definidos por el usuario (clases o estructuras). Usando instrucciones que nos permitan asignar datos y liberar la memoria en tiempo de ejecución. Esto depende del lenguaje que se utilice. En Pascal, por ejemplo con new creamos un objeto de tipo puntero y con dispose se destruye. El tratamiento de memoria dinámica sigue tres pasos fundamentales: 1) Petición de memoria (función malloc) 2) Utilización de dicha memoria para nuestro propósito

3) Liberación de memoria (función free)



Las variables de tipo puntero son las que nos permiten referenciar datos dinámicos. Un puntero es una dirección de memoria. Para definir una variable puntero de un determinado tipo se sigue una sintaxis parecida a la usada para definir variables normales sólo que al nombre del tipo se le postpone un símbolo de asterisco (*) O sea, un puntero se define así: <tipo> * <nombrePuntero>; Por ejemplo, una variable puntero llamada a que pueda almacenar referencias a posiciones de memoria donde se almacenen objetos de tipo int se declara así: int * a; En caso de quererse declarar una tabla de punteros, entonces el asterisco hay que incluirlo tras el nombre del tipo pero antes de los corchetes. Por ejemplo, una tabla de nombre t que pueda almacenar punteros a objetos de tipo int se declara así: int*[] t; Hay un tipo especial de puntero que es capaz de almacenar referencias a objetos de cualquier tipo. Éstos punteros se declaran indicando void como <tipo>. Por ejemplo: void * punteroACualquierCosa; Hay que tener en cuenta que en realidad lo que indica el tipo que se dé a un puntero es cuál es el tipo de objetos que se ha de considerar que se almacenan en la dirección de memoria almacenada por el puntero. Si se le da el valor void lo que se está diciendo es que no se desea que se considere que el puntero apunta a ningún tipo específico de objeto. Es decir, no se está dando información sobre el tipo apuntado.


Se pueden declarar múltiples variables

punteros de tipos que se almacenen en

locales de tipo puntero en una misma

memoria dinámica o contengan miembros

línea. En ese caso el asterisco sólo hay que

que se almacenen en memoria dinámica,

incluirlo antes del nombre de la primera.

ya que entonces podría ocurrir que un

Por ejemplo:

objeto sólo referenciado a través de

int * a, b; // a y b son de tipo int * No

punteros sea destruido por considerar el

sería válido haberlas definido como int *a,

recolector que nadie le referenciaba. Por

*b;

ello, sólo es válido definir punteros de Hay que tener en cuenta que esta

tipos cuyos objetos se puedan almacenar

sintaxis especial para definir en una misma

completamente en pila, pues la vida de

definición varios punteros de un mismo

estos objetos no está controlada por el

tipo sólo es válida en definiciones de

recolector de basura sino que se destruyen

variables locales. Al definir campos no

cuando se abandona el ámbito donde

sirve y hay que dar para cada campo una

fueron definidos.

definición independiente.

En concreto, los únicos punteros válidos

El recolector de basura no tiene en

son aquellos que apunten a tipos valor

cuenta los datos a los que se referencie

básicos, enumeraciones o estructuras que

con punteros, pues ha de conocer cuál es

no contengan campos de tipos referencias.

el objeto al referenciado por cada variable

También pueden definirse punteros a tipos

y un puntero en realidad no tiene porqué

puntero, como se muestra en el siguiente

almacenar referencias a objetos de ningún

ejemplo de declaración de un puntero a

tipo en concreto. Por ejemplo, pueden

punteros

tenerse punteros int * que en realidad

punteroApunteros:

apunten a objeto char, o punteros void *

int ** punteroApunteros;

que no almacenen información sobre el

de

tipo

int

llamando

Obviamente la anidación puede hacerse

tipo de objeto al que debería considerarse

a

que apuntan, o punteros que apunte a

pudiéndose definir punteros a punteros a

direcciones donde no hayan objetos, etc.

punteros, o punteros a punteros a

Como el recolector de basura no trabaja con punteros, no es posible definir

cualquier

nivel

de

punteros a punteros, etc.

profundidad,


La función malloc posee la siguiente sintaxis: [direcc_inicio] malloc([tamaño en bytes]);

[ Para especificar la cantidad de memoria que necesitamos se suele utilizar la función sizeof. [tamaño en bytes] sizeof( [tipo definido] );

Combinando estas funciones podremos reservar memoria para vectores, matrices, etc… Para liberar memoria asignada utilizaremos la función free, especificando la dirección de inicio de la misma. Su sintaxis es la siguiente: free( [direcc_inicio] );

A partir de esta instrucción, la memoria que habíamos reservado podrá ser utilizada por otros procesos del sistema. Veamos las siguientes líneas:

int *ptrEntero; ptrEntero = new int; /*(al puntero ptrEntero le asignamos dinamicamente espacio para contener un valor int)*/

int *ptrEnteroA; ptrEnteroA = new int(5); /*(igual que al anterior pero de paso lo inicializamos en 5)*/ También podríamos hacerlo con un arreglo, para esto: int *arreglo = new int[45]; /* (creamos un arreglo dinámico, ésta vez lo hacemos en la misma línea en la que declaramos el puntero) */ Supongamos ahora que poseemos una clase Punto, podríamos crear objetos dinámicos a partir de esta clase. Punto *ptrQ; ptrQ = new Punto(4,5); /* (en la segunda línea le pasamos además dos parámetros separados por coma al constructor de Punto) */



Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.