Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.1.5 Duración de almacenamiento y ciclo vital

§1 Duración de almacenamiento

La duración de almacenamiento ("Storage duration") de un objeto, es una propiedad estrechamente relacionada con el tipo de almacenamiento. Se define como el mínimo potencial de vida que tiene el almacenamiento que alberga al objeto, y determina el periodo en el que los objetos pueden tener existencia real, es decir, estar alojados físicamente en memoria.  Esta propiedad acompaña al objeto desde el instante de su creación (definición) y depende del modo en que se realizó esta definición.

Existen tres tipos de duración de almacenamiento: estática local (o automática) , y persistente [2] , cuyas características describimos a continuación.

§1.1 Duración estática

Tan pronto como se inicia la ejecución de un programa, los objetos con duración estática reciben su correspondiente asignación de memoria [1], que permanece hasta que finaliza el programa. Si no existe ningún iniciador o constructor explícito, estos objetos son inicializados a cero o nulo ( 4.1.2).

Nota: el Estándar establece que los objetos que no tengan ninguna de las otras duraciones (local o persistente) son de duración estática.


Es importante no confundir el concepto de duración estática con visibilidad global o de fichero, dado que un objeto puede tener duración estática (toda la vida del programa) y ámbito local a un bloque de código; a una función, o a un fichero. La contraria siempre es equivalente, es decir: una variable, por el simple hecho de tener visibilidad global, tiene duración estática.

Donde quiera que sean definidas, todas las funciones tienen duración estática (porque sus identificadores son globales) y como se ha dicho, todas las variables globales a un fichero tienen duración estática por el simple hecho de ser globales. Duración y visibilidad pueden ser conferidas de forma implícita o explícita. La primera, simplemente declarándolas fuera de cualquier función (generalmente al principio del fichero). La declaración explícita se efectúa mediante el uso de los modificadores static ( 4.1.8c) y extern ( 4.1.8d).

Nota: no olvidar que (desgraciadamente, en este sentido el estándar ANSI se presta a confusión) la variable o función global declarada static solo es visible dentro del fichero en que se ha declarado (desde el punto de declaración hasta el final). Es decir, le resta su posibilidad ser visible desde otros ficheros. Sin embargo, este uso confuso puede soslayarse porque el mecanismo de espacio de nombres de C++ permite un artificio por el que una variable global a un fichero solo sea visible dentro del mismo sin necesidad de utilizar la palabra static ( 4.1.11b Subespacios anónimos).


Los objetos locales de clarados con el especificador static se crean en una zona especial de memoria, el montón o "heap" ( 1.3.2) en el momento en que la ejecución del programa llega por primera vez a su declaración. A partir de este momento tienen existencia hasta la finalización del programa.

§1.2 Duración automática

Los objetos de duración local, también conocidos como automáticos, tienen una existencia más precaria (que los estáticos). Son creados en la pila o en un registro cuando entra en ejecución el bloque o función, y son destruidos automáticamente cuando el programa sale del bloque o función. C++ dispone de una palabra clave específica para este fin: auto ( 4.1.8a). Ejemplo:

int func(int z) {
   auto int i;
   i = 5;

   int j = 5;
   return (i+z);
}

Sin embargo este especificador raramente se usa, ya que es innecesario y redundante, pues auto es el tipo asignado por defecto a las variables declaradas dentro de cualquier bloque o función, de forma que las variables i y j del ejemplo anterior tienen las mismas propiedades.

En los objetos con duración local, su ámbito también es local al bloque o función. Pero la inversa no es necesariamente cierta, los objetos con ámbito local pueden tener duración no automática.

Cuando una variable automática sale de su ámbito, es llamado implícitamente su destructor. En las variables locales esto ocurre cuando el bloque en que son declaradas deja de estar activo. En las variables globales los destructores son llamados como parte del proceso de salida de la función main. Estos destructores son llamados exactamente en el orden inverso en que fueron llamados sus constructores.

 Ojo: cuando un puntero a un objeto sale de ámbito no es llamado implícitamente ningún destructor para el objeto señalado [4], lo que significa que es necesario utilizar el operador delete para destruir el objeto (salvo que el objeto se destruya a su vez por su cuenta).

Ejemplo:

{

  int x = 10;          // L.2 Ok crea un int

  int* pt1 = &x;       // L.3 Ok crea un int*

  int* pt2;            // L.4 Ok crea un int*

  pt2 = new(int);      // L.5 Ok crea un int (1)

  ...

  delete pt2;          // L.7: Ok. destruido int(1) *pt2

}                      // L.8: Ok destruidos x, pt1 y pt2


Los objetos de duración local deben ser iniciados explícitamente, de otro modo su contenido es imprevisible (simplemente basura) [3].  Aunque pueden ser declarados explícitamente con el modificador auto, hemos señalado que es innecesario, ya que este es el tipo asignado por defecto a las variables declaradas dentro de cualquier bloque o función.

Nota: cuando se aplica el especificador de almacenamiento register ( 4.1.8b) a la declaración de variables (por ejemplo, int, charfloat), además de pasar una petición al compilador para que, caso de ser posible, sitúe el objeto en un registro, implica también duración automática (auto).

§1.3 Duración persistente

Los objetos persistentes (también llamados dinámicos) son creados y destruidos por llamadas a funciones específicas. Son creados en una reserva especial de memoria conocida como montón (heap 1.3.2) utilizando cualquier función de librería estándar como malloc o el operador new ( 4.9.20). La destrucción debe realizarse explícitamente con free o delete ( 4.9.21).

Aún a riesgo de ser pelmazos, es importante insistir en que, salvo que se adopten medidas especiales, la destrucción de los objetos persistentes se realiza siempre mediante la utilización explícita (por el programador) de las funciones mencionadas. Recordar que con estos objetos no ocurre lo mismo que con los automáticos . En aquellos la única preocupación del programador es crearlos, ya que al salir de ámbito serán automáticamente destruidos por el compilador. Estos en cambio, deben ser destruidos explícitamente.

§2 Ciclo vital

El tiempo de vida o ciclo vital ("Lifetime") de un objeto es una propiedad de tiempo de ejecución ("Runtime"). Viene determinado por el lapso entre su creación y su destrucción. Por supuesto no puede exceder la duración de su almacenamiento.

El ciclo vital comienza cuando se le asigna espacio de almacenamiento y, si no es un objeto trivial, cuando el objeto es convenientemente iniciado por su constructor. Finaliza cuando es llamado el destructor o se rehúsa la zona de almacenamiento que le había sido asignada.

Nota: decimos que un objeto es trivial cuando es, por ejemplo, un tipo simple preconstruido en el lenguaje. En este caso una expresión del tipo

int x;

basta para que el compilador pueda reservar espacio de almacenamiento.


Observe que el ciclo vital de los objetos automáticos y estáticos es controlado automáticamente por el compilador. En los primeros la destrucción se realiza cuando el objeto sale de ámbito. En los segundos la destrucción ocurre con las rutinas de finalización del programa. Por su parte el ciclo vital de los objetos dinámicos es controlado por el programador.

  Inicio.


[1] Generalmente esta memoria reside en un segmento de datos fijo, situado de acuerdo con el modelo de memoria que se esté utilizando, aunque en los ambientes de 32 bits de PC y compatibles, solo está disponible el denominado modelo plano ("Flat memory model").

[2] Esta última, denominada "dinámica" en la mayoría de los textos, incluyendo la propia literatura inglesa (por ejemplo los manuales de Borland), nos parece un término desafortunado para designar la duración de los objetos almacenados en el montón ( 1.3.2). Por esta razón preferimos designarlos como objetos "persistentes", ya que esta palabra califica más adecuadamente las características de tales objetos.

[3] Precisamente por esto y en especial si se trata de punteros, su uso puede resultar peligroso si no son inicializados correctamente.

[4] Hay una excepción en los llamados punteros inteligentes que destruyen el objeto señalado antes de ser ellos mismos destruidos ( 4.12.2b1).