La durée de vie des static
variables de fonction commence la première fois [0] que le flux de programme rencontre la déclaration et se termine à la fin du programme. Cela signifie que le run-time doit effectuer une comptabilité afin de le détruire uniquement s'il a été réellement construit.
De plus, comme la norme stipule que les destructeurs d'objets statiques doivent s'exécuter dans l'ordre inverse de l'achèvement de leur construction [1] et que l'ordre de construction peut dépendre de l'exécution spécifique du programme, l'ordre de construction doit être pris en compte .
Exemple
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);
}
Production:
C:> sample.exe
Créé dans foo
Détruit dans foo
C:> sample.exe 1
Créé dans if
Créé dans foo
Détruit dans foo
Détruit dans if
C:> sample.exe 1 2
Créé dans foo
Créé dans if
Destroyed dans if
Destroyed in foo
[0]
Étant donné que C ++ 98 [2] n'a aucune référence à plusieurs threads, la façon dont cela se comportera dans un environnement multithread n'est pas spécifiée et peut être problématique comme le mentionne Roddy .
[1]
Section C ++ 98 3.6.3.1
[basic.start.term]
[2]
En C ++ 11, les statiques sont initialisées de manière sécurisée pour les threads, ce qui est également connu sous le nom de Magic Statics .
[basic.start.term]
Motti a raison sur la commande, mais il y a d'autres choses à considérer:
Les compilateurs utilisent généralement une variable d'indicateur masqué pour indiquer si la statique locale a déjà été initialisée, et cet indicateur est vérifié à chaque entrée de la fonction. Évidemment, il s'agit d'un petit succès de performances, mais ce qui est plus préoccupant, c'est que cet indicateur n'est pas garanti pour être thread-safe.
Si vous avez une statique locale comme ci-dessus et que
foo
vous êtes appelé à partir de plusieurs threads, vous pouvez avoir des conditions de concurrence provoquantplonk
une initialisation incorrecte ou même plusieurs fois. De plus, dans ce cas, ilplonk
peut être détruit par un thread différent de celui qui l'a construit.Malgré ce que dit la norme, je me méfierais de l'ordre réel de la destruction statique locale, car il est possible que vous vous appuyiez involontairement sur une statique toujours valide après sa destruction, et c'est vraiment difficile à retrouver.
la source
Les explications existantes ne sont pas vraiment complètes sans la règle réelle de la norme, trouvée en 6.7:
la source
FWIW, Codegear C ++ Builder ne détruit pas dans l'ordre attendu selon la norme.
... ce qui est une autre raison de ne pas se fier à l'ordre de destruction!
la source
le variables statiques entrent en jeu une fois l' exécution du programme commencée et restent disponibles jusqu'à la fin de l'exécution du programme.
Les variables statiques sont créées dans le segment de données de la mémoire .
la source