Inicialização
Inicialização de uma variável provê seu valor inicial no tempo de construção.
O valor inicial pode ser provido na seção de inicializador de um declarador ou uma expressão new. Também pode acontecer durante chamadas de função: parâmetros de função e valores de retorno de função também são inicializados.
Para cada declarador, o inicializador pode ser uma das seguintes:
( expression-list )
|
(1) | ||||||||
= expression
|
(2) | ||||||||
{ initializer-list }
|
(3) | ||||||||
Dependendo do contexto, o inicializador pode invocar:
- Inicialização de valor, e.g. std::string s{};
- Inicialização direta, e.g. std::string s("olá");
- Incialização de cópia, e.g. std::string s = "olá";
- Inicialização de lista, e.g. std::string s{'a', 'b', 'c'};
- Inicialização de agregado, e.g. char a[3] = {'a', 'b'};
- Inicialização de referência, e.g. char& c = a[0];
Se nenhum inicializador é provido, as regras de inicialização default aplicam-se.
Índice |
[editar] Variáveis não-locais
Todas as variável não-locais com duração de armazenamento estática são inicializadas como parte de arranque de programa, antes da execução da função main começa (a menos que diferida, veja abaixo). Todas as variáveis não-locais com duração de armazenamento thread-local são inicializadas como parte de lançamento de thread, sequenciadas-antes de a execução da função de thread começar. Para ambas destas classes de variáveis, a inicialização ocorre em dois estágios distintos:
[editar] Inicialização estática
Há duas formas de inicialização estática:
Em ptrática:
- Inicialização constante é normalmente aplicada a tempo de compilação. Representações de objeto pré-calculadas são armazenadas como parte da imagem de programa. Se o compilador não fizer isso, ele ainda deve garantir que a inicialização acontece antes de qualquer inicialização dinâmica.
- Variáveis por ser zero-inicializadas são postas no segmento
.bss
da imagem de programa, que não ocupa nenhum espaço em disco e é zerado pelo OS ao carregar o programa.
[editar] Inicialização dinâmica
Depois que toda a inicialização estática é completada, inicialização de variáveis não-locais ocorre nas seguintes situações:
2) Inicialização dinâmica parcialmente ordenada, que se aplica a todas as variáveis inline que não são uma especialização instanciada implicitament ou explicitamente. Se uma V parcialmente ordenada é definida antes de W ordenada ou parcialmente ordenada em toda unidade de tradução, a inicialização de V é sequenciada antes da inicialização de W (ou acontece-antes, se o programa começar um thread).
|
(desde C++17) |
Se a inicialização de uma variável não-local com duração de armazenamento estático ou de thread existir via uma exceção, std::terminate é chamada.
[editar] Incialização dinâmica precoce
Os compiladores são permitios inicializar variáveis inicializadas dinamicamente como parte de inicialização estática (essencialmente, e tempo de compilação), se as seguintes condições são ambas verdadeiras:
Por causa da regra acima, se inicialização de algum objeto o1
se referir a um objeto de escopo-namespace o2
, que potencialmente requer inicialização dinâmica, mas é definidor mais depois na mesma unidade de tradução, é não-especificado se o valor de o2
usado será o valor da o2
completamente inicializada (porque o compilador promoveu inicialização de o2
para tempo de compilação) ou será o valor de o2
meramente zero-inicializado.
inline double fd() { return 1.0; } extern double d1; double d2 = d1; // não-especificado: // inicializada dinamicamente para 0.0 se d1 é inicializada dinamicamente, ou // inicializada dinamicamente para 1.0 se d1 é inicializada estaticamente, ou // inicializada estaticamente para 0.0 (porque isso seria seu valor // se ambas variáveis fossem inicializadas dinamicamente) double d1 = fd(); // pode ser inicializado estaticamente or dinamicamente para 1.0
[editar] Incialização dinâmica diferida
É definido pela implementação se inicialização dinâmica acontesse-antes da primeira instrução da função main (para estáticas) ou da função inicial da thread (para thread-locals), ou difereda para acontecer depois.
Se a inicialização de uma variável não-inline (desde C++17) é diferida para acontecer depois da primeira instrução da função main/de thread, ela acontece antes do primeiro uso-odr de qualquer variável com duração de armazenamento estática/de thread definida na mesma unidade de tradução como a variável a ser inicializada. Se nenhuma variável ou função é odr-usada de uma dada unidade de tradução, as variáveis não-locais definidas nessa unidade de tradução nunca poderão ser inicializadas (isto modela o comportamente de uma biblioteca dinâmica on-demand). Porém, contanto que qualquer coisa de uma unidade de tradução seja odr-usada, todas as variáveis não-locais cuja inicialização ou destruição têm efeitos colaterais vão ser inicializadas mesmo se ela não são usadas no programa.
Se a inicialização de uma variável inline é diferida, ela acontece antes do primeiro uso-odr dessa variávele específica.
|
(desde C++17) |
// - Arquivo 1 - #include "a.h" #include "b.h" B b; A::A(){ b.Usar(); } // - Arquivo 2 - #include "a.h" A a; // - Arquivo 3 - #include "a.h" #include "b.h" extern A a; extern B b; int main() { a.Usar(); b.Usar(); } // Se a é inicializada antes que mail é entrada, b pode ainda ser não-inicializada // no ponto onde A::A() a usa (porque init dinâmica é indeterminadamente sequenciada // através de unidades de tradução) // Se a é inicializada a algum ponto depois que a primeira instrução de (que odr-usa // uma função definida em Arquivo 1, forçando sua inicialização dinâmica a executar), // então b vai ser inicializado antes de seu uso em A::A
[editar] Variáveis locais estáticas
Para incialização de variáveis estáticas e thread-local locais (isso é, escopo de bloco) static and thread-local variables, see static local variables.
Initializer is not allowed in a block-scope declaration of a variable with external or internal linkage. Such a declaration must appear with extern and cannot be a definition.
[editar] Membros de classe
Membros de dados não-estáticos podem ser inicializados com lista de inicializador de membro ou com uma inicializador de membro default.
[editar] Notas
A ordem de destruição de variáveis não-locais é descrita em std::exit.
[editar] Veja também
- elisão de cópia
- construtor de conversão
- construtor de cópia
- construtor default
- explicit
- construtor de moção
- new
Documentação C para Inicialização
|