Inicialización
La inicialización de una variable provee su valor inicial en el momento de la construcción.
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) | ||||||||
Dependiendo del contexto, el inicializador puede invocar:
- Inicialización de un valor, p. ej., std::string s{};
- Inicialización directa, p. ej., std::string s("hola");
- Inicialización de copia, p. ej., std::string s ="hola";
- Inicialización de lista, p. ej., std::string s{'a', 'b', 'c'};
- Inicialización de agregado, p. ej., char a[3]={'a', 'b'};
- Inicialización de referencia, p. ej., char& c = a[0];
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
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.
- 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:
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) |
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:
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.
inlinedouble fd(){return1.0;}externdouble 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.
No se permite un inicializador en una declaración de una variable en ámbito de bloque con enlace externo o interno. Tal declaración debe aparecer con extern y no puede ser una definición.
[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. |