Respostas:
A vida útil das static
variáveis de função começa na primeira vez que [0] o fluxo do programa encontra a declaração e termina na finalização do programa. Isso significa que o tempo de execução deve executar alguma manutenção contábil para destruí-lo somente se ele foi realmente construído.
Além disso, como o padrão diz que os destruidores de objetos estáticos devem ser executados na ordem inversa da conclusão de sua construção [1] , e a ordem de construção pode depender da execução específica do programa, a ordem de construção deve ser levada em consideração .
Exemplo
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Resultado:
C:> sample.exe
criado em foo
Destruído em fooC:> sample.exe 1
Criado em se
Criado em foo
Destruído em foo
Destruído em seC:> sample.exe 1 2
Criado em foo
Criado em se
Destruído em se
Destruído em foo
[0]
Como o C ++ 98 [2] não tem referência a vários threads, como isso se comportará em um ambiente com vários threads não é especificado e pode ser problemático, como Roddy menciona.
[1]
Seção C ++ 98 3.6.3.1
[basic.start.term]
[2]
No C ++ 11, as estáticas são inicializadas de maneira segura para threads, isso também é conhecido como Magic Statics .
[basic.start.term]
Motti está certo sobre o pedido, mas há outras coisas a considerar:
Os compiladores geralmente usam uma variável de sinalizador oculta para indicar se as estatísticas locais já foram inicializadas e esse sinalizador é verificado em todas as entradas da função. Obviamente, esse é um pequeno impacto no desempenho, mas o que é mais preocupante é que esse sinalizador não é garantido como seguro para threads.
Se você tem uma estática local, como acima, e foo
é chamado de vários encadeamentos, pode haver condições de corrida que plonk
podem ser inicializadas incorretamente ou mesmo várias vezes. Além disso, nesse caso, plonk
pode ser destruído por um thread diferente daquele que o construiu.
Apesar do que diz o padrão, eu ficaria muito cauteloso com a ordem real da destruição estática local, porque é possível que você involuntariamente confie em uma estática ainda válida após ser destruída, e isso é realmente difícil de rastrear.
As explicações existentes não são realmente completas sem a regra real da Norma, encontrada em 6.7:
A inicialização zero de todas as variáveis de escopo de bloco com duração de armazenamento estático ou duração de armazenamento de encadeamento é executada antes de qualquer outra inicialização. A inicialização constante de uma entidade de escopo de bloco com duração de armazenamento estático, se aplicável, é executada antes do primeiro bloco ser inserido. É permitida uma implementação para executar a inicialização antecipada de outras variáveis do escopo de bloco com duração de armazenamento estático ou de encadeamento nas mesmas condições em que uma implementação pode inicializar estaticamente uma variável com duração de armazenamento estático ou de encadeamento no escopo do espaço para nome. Caso contrário, essa variável é inicializada na primeira vez em que o controle passa por sua declaração; essa variável é considerada inicializada após a conclusão de sua inicialização. Se a inicialização sair lançando uma exceção, a inicialização não está completa, portanto, será tentada novamente na próxima vez que o controle entrar na declaração. Se o controle digitar a declaração simultaneamente enquanto a variável estiver sendo inicializada, a execução simultânea aguardará a conclusão da inicialização. Se o controle entrar novamente na declaração recursivamente enquanto a variável estiver sendo inicializada, o comportamento será indefinido.
FWIW, o Codegear C ++ Builder não destrói na ordem esperada, de acordo com o padrão.
C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if
... que é outra razão para não confiar na ordem de destruição!
As variáveis estáticas são ativadas quando a execução do programa é iniciada e permanecem disponíveis até o término da execução do programa.
As variáveis estáticas são criadas no segmento de dados da memória .