Espacios de nombres
Variantes
Acciones

Inicialización

De cppreference.com
< cpp‎ | language

La inicialización de una variable provee su valor inicial en el tiempo en el que se construye.

El valor inicial se puede proporcionar en la sección de inicialización de un declarador o una expresión new. También tiene lugar durante las llamadas a función: los parámetros de función y los valores de retorno de función también se inicializan.

Para cada declarador, el inicializador puede ser uno de los siguientes:

( lista-de-expresiones ) (1)
= expresión (2)
{ lista-de-inicializadores } (3)
1) Lista separada por comas de expresiones arbitrarias y listas de inicializadores entre llaves en paréntesis.
2) El signo igual seguido de una expresión
3) Lista de inicializadores entre llaves: posiblemente vacía, lista separada por comas de expresiones y otras listas de inicializadores entre llaves.

Dependiendo del contexto, el inicializador puede invocar:

Si no se proporciona un inicializador, se aplican las reglas de inicialización por defecto.

Contenido

[editar] Variables no locales

Todas las variables no locales con duración de almacenamiento estática se inicializan como parte del inicio del programa, antes de que comience la ejecución de la función main (a menos que se posponga, véase más abajo). Todas las variables no locales con duración de almacenamiento local al hilo se inicializan como parte del inicio del hilo, secuenciadas antes de que comience la ejecución de la función del hilo. Para ambas clases de variables, la inicialización ocurre en dos etapas distintas:

[editar] Inicialización estática

1) Si está permitido, la inicialización por constante tiene lugar primero (véase inicialización por constante para ver la lista de esas situaciones). En la práctica, la inicialización por constante generalmente se realiza en tiempo de compilación, y las representaciones de objetos precalculadas se almacenan como parte de la imagen del programa. Si el compilador no hace eso, aún debe garantizar que esta inicialización ocurra antes de cualquier inicialización dinámica.
2) Para todas las demás variables estáticas no locales y locales al hilo, tiene lugar la inicialización cero. En la práctica, las variables que se van a inicializar a cero se colocan en el segmento .bss de la imagen del programa, que no ocupa espacio en el disco, y el sistema operativo lo pone a cero al cargar el programa.

[editar] Inicialización dinámica

Después de completar toda la inicialización estática, la inicialización dinámica de variables no locales ocurre en las siguientes situaciones:

1) La inicialización dinámica no ordenada, que se aplica solo a los datos miembro estáticos de plantillas de clase (estáticas o locales al hilo) y plantillas de variable (desde C++14) que no son especializadas explícitamente. La inicialización de tales variables estáticas se secuencia indeterminadamente con respecto a todas las demás inicializaciones dinámicas excepto si el programa inicia un hilo antes de que se inicialice una variable, en cuyo caso su inicialización no tiene secuencia (desde C++17). La inicialización de tales variables locales al hilo no está secuenciada con respecto a todas las demás inicializaciones dinámicas.
2) La inicialización dinámica parcialmente ordenada, que se aplica a todas las variables en línea que no son una especialización implícita o explícitamente instanciada. Si se define una V parcialmente ordenada antes de una W ordenada o parcialmente ordenada en cada unidad de traducción, la inicialización de V se secuencia antes de la inicialización de W (o sucede antes, si el programa inicia un hilo).
(desde C++17)
3) La inicialización dinámica ordenada, que se aplica a todas las demás variables no locales: dentro de una sola unidad de traducción, la inicialización de estas variables siempre es secuenciada en el orden exacto en que aparecen sus definiciones en el código fuente. La inicialización de variables estáticas en diferentes unidades de traducción se secuencia indeterminadamente. La inicialización de variables locales al hilo en diferentes unidades de traducción no está secuenciada.

Si la inicialización de una variable no local con una duración de almacenamiento estática o de hilo termina por una excepción, se llama a std::terminate.

[editar] Inicialización dinámica temprana

Los compiladores pueden inicializar variables inicializadas dinámicamente como parte de la inicialización estática (esencialmente, en tiempo de compilación), si las siguientes condiciones son verdaderas:

1) la versión dinámica de la inicialización no cambia el valor de ningún otro objeto del ámbito del espacio de nombres antes de su inicialización;
2) la versión estática de la inicialización produce el mismo valor en la variable inicializada que se produciría con la inicialización dinámica si todas las variables que no requieren inicializarse estáticamente se inicializan dinámicamente.

Debido a la regla anterior, si la inicialización de algún objeto o1 se refiere a un objeto o2 en ámbito del espacio de nombres, que potencialmente requiere inicialización dinámica, pero se define más adelante en la misma unidad de traducción, no se especifica si el valor de o2 utilizado será el valor de o2 totalmente inicializado (porque el compilador promovió la inicialización de o2 al tiempo de compilación) o será el valor de o2 simplemente inicializado a cero.

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1;   // no especificado:
                  // inicializada dinámicamente a 0.0 si d1 es inicializada dinámicamente, o
                  // inicializada dinámicamente a 1.0 si d1 es inicializada estáticamente, o
                  // inicializada estáticamente a 0.0 (porque ese sería su valor
                  // si ambas variables fueron inicializadas dinámicamente)
double d1 = fd(); // puede ser inicializada estáticamente o dinámicamente a 1.0

[editar] Inicialización dinámica aplazada

Se define en la implementación si la inicialización dinámica ocurre antes de la primera declaración de la función main (para estáticas) o la función inicial del hilo (para locales al hilo), o pospuesta para que suceda después.

Si la inicialización de una variable no en línea (desde C++17) se aplaza después de la primera instrucción de la función main o del hilo, ocurre antes del primer uso ODR de cualquier variable con una duración de almacenamiento estático o local al hilo definida en la misma unidad de traducción que la variable que se va a inicializar. Si ninguna variable o función de una unidad de traducción dada tiene uso ODR, las variables no locales definidas en esa unidad de traducción puede ser que nunca se inicialicen (esto modela el comportamiento de una biblioteca dinámica a pedido). Sin embargo, siempre y cuando cualquier elemento de una unidad de traducción tenga uso ODR, todas las variables no locales cuya inicialización o destrucción tenga efectos secundarios se inicializarán incluso si no se usan en el programa.

Si la inicialización de una variable en línea se pospone, sucede antes del primer uso ODR de esa variable específica.

(desde C++17)
// - Archivo 1 -
#include "a.h"
#include "b.h"
B b;
A::A(){ b.Use(); }
 
// - Archivo 2 -
#include "a.h"
A a;
 
// - Archivo 3 -
#include "a.h"
#include "b.h"
extern A a;
extern B b;
 
int main() {
    a.Use();
    b.Use();
}
 
// Si a se inicializa antes de entrar a main , b aun puede estar sin inicializar
// en el punto donde A::A() la utiliza (porque la inic. dinámica es secuenciada
// indeterminadamente a través de las unidades de traducción)
 
// Si a se inicializa en algún punto después de la primera instrucción de main
// (que hace uso ODR de una función definida en Archivo 1, fuerza a que se
// ejecute su inicialización dinámica), entonces b se inicializará antes de
// que se use en A::A

[editar] Variables locales estáticas

Para la inicialización de variables locales (es decir, en ámbito de bloque) estáticas y variables locales al hilo, véase variables locales estáticas.

[editar] Miembros de clase

Los datos miembro no estáticos pueden inicializarse con la lista de inicializadores de miembros o con un inicializador de miembro por defecto.

[editar] Notas

El orden de destrucción de las variables no locales se describe en std::exit.

[editar] Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
CWG 2026 C++14 Se especificaba que la inicialización cero siempre ocurriera

primero, incluso antes de la inicialización por constante

No ocurre la inicialización cero si se aplica la inicialización

por constante.

[editar] Véase también