32 - Pila dinámica


Otra utilización fundamental de los punteros es para hacer uso de la pila dinámica de la memoria que administra el sistema operativo.

Lo primero que veremos es que todas las variables que definimos ocupan un espacio llamado PILA ESTATICA del programa (esta pila estática es limitada)

A medida que definimos variables se reduce el espacio disponible para definir otras variables.

Por ejemplo si definimos un vector con 10000 componentes de tipo entero en la función main debemos tener en cuenta que 40 Kb (si cada entero ocupa 4 bytes) de la pila estática estará reservado para dicha estructura.

Es común que en programas de mediano y gran tamaño la pila estática no nos alcance para almacenar los datos. En estos casos debemos recurrir a la PILA DINAMICA.

La PILA DINAMICA solo se puede acceder por medio de punteros.
La pila dinámica solo esta limitada por la cantidad de memoria ram del equipo.

pila dinamica

Podemos observar que la memoria del equipo tiene cargado el sistema operativo que administra entre otras cosas los programas que se ejecutan. Todo programa que se ejecuta (Exe) tiene asignado un espacio para la pila estática (puede variar a partir, por ejemplo 64 Kb.)

La pila dinámica es toda la memoria Ram que no es ocupada por el sistema operativo y otros programas que están ejecutándose actualmente

.

Para acceder al espacio de memoria llamada Pila Dinámica debemos solicitarla al sistema operativo.

Para solicitar espacio en la pila dinámica debemos utilizar el operador new y es fundamental devolverla mediante el operador delete (la no devolución del espacio solicitado hará que nuestra computadora en algún momento se bloquee por falta de espacio en la memeoria ram)

La administración de la memoria dinámica ofrece una gran libertad al programador pero trae como contrapartida una gran responsabilidad para administrarla correctamente.

Problema 1:

Definir un vector de 5 elementos y localizarlo en la pila dinámica.

Programa:

#include<iostream>

using namespace std;

void main ()
{
  int *p;
  p=new int[5];
  for(int f=0;f<5;f++)
  {
    cout <<"Ingrese elemento:";
    cin >>p[f];
  }
  cout <<"contenido del vector:";
  for(int f=0;f<5;f++)
  {
    cout<<p[f]<<"-";
  }
  delete []p;
  cin.get();
  cin.get();
}

Este proyecto lo puede descargar en un zip desde este enlace : PilaDinamica1.zip

Para crear un vector en la pila dinámica debemos utilizar el operador new:

  int *p;
  p=new int[5];

Como vemos es distinta la sintaxis a la creación de un vector estático: int p[5]

Cuando trabajamos con el vector no hay cambios con respecto a lo que hemos visto con vectores estáticos (cargarlo, imprimirlo etc.):

  for(int f=0;f<5;f++)
  {
    cout <<"Ingrese elemento:";
    cin >>p[f];
  }
  cout <<"contenido del vector:";
  for(int f=0;f<5;f++)
  {
    cout<<p[f]<<"-";
  }

Y finalmente otro punto nuevo a tener en cuenta cuando trabajamos con variables localizadas en la pila dinámica es devolver el espacio utilizado:

  delete []p;

La localización de variables en la pila dinámica trae consigo dos ventajas, por una parte la pila dinámica es mucho más grande que la pila estática por lo que podemos definir muchas más variables que en la pila estática.
Por otro lado podemos solicitar espacio para estructuras de datos en tiempo de ejecución (Por ejemplo podemos definir un vector con una cantidad de componentes que dependa de una variable)

Problema 2:

Plantear una clase que permita administrar un vector de enteros. En el constructor solicitar al operador que ingrese la cantidad de componentes que tendrá el vector y lo cree y localice en la pila dinámica. Hacer un método que lo imprima y finalmente en el destructor eliminar el espacio ocupado por el vector creado previamente.

Programa:

#include<iostream>

using namespace std;

class Vector {
    int *p;
    int tamano;
public:
    Vector();
    void cargar();
    void imprimir();
    ~Vector();
};

Vector::Vector()
{
    cout <<"Cuantos elementos tendra el vector:";
    cin >>tamano;
    p=new int[tamano];
}

void Vector::cargar()
{
    for(int f=0;f<tamano;f++)
    {
        cout <<"Ingrese elemento:";
        cin>>p[f];
    }
}

void Vector::imprimir()
{
    for(int f=0;f<tamano;f++)
    {
        cout<<p[f];
        cout<<"-";
    }
}

Vector::~Vector()
{
    delete []p;
}

void main()
{
    Vector vector1;
    vector1.cargar();
    vector1.imprimir();
    cin.get();
    cin.get();
}

Este proyecto lo puede descargar en un zip desde este enlace : PilaDinamica2.zip

Definimos dos atributos, el puntero y una variable entera que indicará el tamaño del vector que quiere crear el usuario:

class Vector {
    int *p;
    int tamano;
public:
    Vector();
    void cargar();
    void imprimir();
    ~Vector();
};

En el constructor solicitamos que ingrese el tamaño del vector y lo creamos en la pila dinámica:

Vector::Vector()
{
    cout <<"Cuantos elementos tendra el vector:";
    cin >>tamano;
    p=new int[tamano];
}

La carga y la impresión del vector:

void Vector::cargar()
{
    for(int f=0;f<tamano;f++)
    {
        cout <<"Ingrese elemento:";
        cin>>p[f];
    }
}

void Vector::imprimir()
{
    for(int f=0;f<tamano;f++)
    {
        cout<<p[f];
        cout<<"-";
    }
}

En el destructor procedemos a liberar el espacio que había sido solicitado para crear el vector:

Vector::~Vector()
{
    delete []p;
}

En la main creamos un objeto de la clase Vector y llamamos a los métodos de cargar e imprimir (recordemos que el constructor se llama automáticamente, lo mismo que el destructor):

void main()
{
    Vector vector1;
    vector1.cargar();
    vector1.imprimir();
    cin.get();
    cin.get();
}

Retornar