J'étais curieux à ce sujet, j'ai donc écrit le programme de test suivant et l'ai compilé avec g ++ version 4.1.2.
include <iostream>
#include <string>
using namespace std;
class test
{
public:
test(const char *name)
: _name(name)
{
cout << _name << " created" << endl;
}
~test()
{
cout << _name << " destroyed" << endl;
}
string _name;
};
test t("global variable");
void f()
{
static test t("static variable");
test t2("Local variable");
cout << "Function executed" << endl;
}
int main()
{
test t("local to main");
cout << "Program start" << endl;
f();
cout << "Program end" << endl;
return 0;
}
Les résultats n'étaient pas ce à quoi je m'attendais. Le constructeur de l'objet statique n'a été appelé que lors du premier appel de la fonction. Voici la sortie:
global variable created
local to main created
Program start
static variable created
Local variable created
Function executed
Local variable destroyed
Program end
local to main destroyed
static variable destroyed
global variable destroyed
Quelques verbiage pertinents de C ++ Standard:
la source
If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration.
La mémoire de toutes les variables statiques est allouée au chargement du programme. Mais les variables statiques locales sont créées et initialisées la première fois qu'elles sont utilisées, pas au démarrage du programme. Il y a de bonnes lectures à ce sujet, et sur la statique en général, ici . En général, je pense que certains de ces problèmes dépendent de la mise en œuvre, en particulier si vous voulez savoir où en mémoire ces éléments seront situés.
la source
Le compilateur allouera des variables statiques définies dans une fonction
foo
au chargement du programme, mais le compilateur ajoutera également des instructions supplémentaires (code machine) à votre fonctionfoo
afin que la première fois qu'il soit appelé, ce code supplémentaire initialise la variable statique ( par exemple en invoquant le constructeur, le cas échéant).@Adam: Cette injection de code dans les coulisses par le compilateur est la raison du résultat que vous avez vu.
la source
J'essaye de tester à nouveau le code d' Adam Pierce et j'ai ajouté deux autres cas: variable statique dans la classe et type POD. Mon compilateur est g ++ 4.8.1, sous Windows OS (MinGW-32). Le résultat est une variable statique dans la classe est traitée de la même manière avec la variable globale. Son constructeur sera appelé avant d'entrer la fonction principale.
Conclusion (pour g ++, environnement Windows):
(1) : L'état correct doit être: "avant qu'une fonction de la même unité de traduction ne soit appelée". Cependant, pour simple, comme dans l'exemple ci-dessous, alors c'est la fonction principale .
inclure <iostream>
résultat:
Quelqu'un testé dans l'environnement Linux?
la source
Les variables statiques sont allouées à l'intérieur d'un segment de code - elles font partie de l'image exécutable et sont donc mappées dans déjà initialisées.
Les variables statiques dans la portée de la fonction sont traitées de la même manière, la portée est purement une construction au niveau du langage.
Pour cette raison, vous avez la garantie qu'une variable statique sera initialisée à 0 (sauf si vous spécifiez autre chose) plutôt qu'une valeur indéfinie.
Il existe d'autres facettes de l'initialisation dont vous pouvez tirer parti - par exemple, les segments partagés permettent à différentes instances de votre exécutable s'exécutant en même temps d'accéder aux mêmes variables statiques.
En C ++ (à portée globale), les objets statiques ont leurs constructeurs appelés dans le cadre du démarrage du programme, sous le contrôle de la bibliothèque d'exécution C. Sous Visual C ++, au moins l'ordre dans lequel les objets sont initialisés peut être contrôlé par le pragma init_seg .
la source
Oui, ça l'est. Ceci, entre autres, vous permet d'initialiser les structures de données accessibles globalement lorsque cela est approprié, par exemple à l'intérieur de blocs try / catch. Par exemple au lieu de
tu peux écrire
et utilisez-le dans le bloc try / catch. Au premier appel, la variable sera initialisée. Ensuite, au premier et au prochain appel, sa valeur sera retournée (par référence).
la source