Ce qui suit n'est bien sûr pas tout à fait précis. Prenez-le avec un grain de sel quand vous le lisez :)
Eh bien, les trois choses auxquelles vous faites référence sont la durée de stockage automatique, statique et dynamique , qui a quelque chose à voir avec la durée de vie des objets et le moment où ils commencent leur vie.
Durée de stockage automatique
Vous utilisez la durée de stockage automatique pour les données de courte durée et de petite taille , qui n'est nécessaire que localement dans un bloc:
if(some condition) {
int a[3]; // array a has automatic storage duration
fill_it(a);
print_it(a);
}
La durée de vie se termine dès que nous sortons du bloc, et elle démarre dès que l'objet est défini. Il s'agit du type de durée de stockage le plus simple et beaucoup plus rapide que la durée de stockage dynamique en particulier.
Durée de stockage statique
Vous utilisez la durée de stockage statique pour les variables libres, auxquelles n'importe quel code peut accéder à tout moment, si leur portée permet une telle utilisation (étendue de l'espace de noms), et pour les variables locales qui doivent étendre leur durée de vie à la sortie de leur étendue (portée locale), et pour les variables membres qui doivent être partagées par tous les objets de leur classe (portée des classes). Leur durée de vie dépend de la portée qu'ils sont. Ils peuvent avoir la portée d'espace de noms et la portée locale et la portée de la classe . Ce qui est vrai pour les deux, c'est qu'une fois leur vie commencée, leur vie se termine à la fin du programme . Voici deux exemples:
// static storage duration. in global namespace scope
string globalA;
int main() {
foo();
foo();
}
void foo() {
// static storage duration. in local scope
static string localA;
localA += "ab"
cout << localA;
}
Le programme imprime ababab
, car il localA
n'est pas détruit à la sortie de son bloc. Vous pouvez dire que les objets qui ont une portée locale commencent leur vie lorsque le contrôle atteint leur définition . Car localA
, cela se produit lorsque le corps de la fonction est entré. Pour les objets dans la portée de l'espace de noms, la durée de vie commence au démarrage du programme . Il en va de même pour les objets statiques de portée de classe:
class A {
static string classScopeA;
};
string A::classScopeA;
A a, b; &a.classScopeA == &b.classScopeA == &A::classScopeA;
Comme vous le voyez, classScopeA
n'est pas lié à des objets particuliers de sa classe, mais à la classe elle-même. L'adresse des trois noms ci-dessus est la même et tous désignent le même objet. Il existe une règle spéciale sur le moment et la manière dont les objets statiques sont initialisés, mais ne nous en préoccupons pas maintenant. Cela signifie le terme fiasco d'ordre d'initialisation statique .
Durée de stockage dynamique
La dernière durée de stockage est dynamique. Vous l'utilisez si vous souhaitez que des objets vivent sur une autre île et que vous souhaitez placer des pointeurs autour de cette référence. Vous les utilisez également si vos objets sont volumineux et si vous souhaitez créer des tableaux de taille connue uniquement à l' exécution . En raison de cette flexibilité, les objets ayant une durée de stockage dynamique sont compliqués et lents à gérer. Les objets ayant cette durée dynamique commencent leur durée de vie lorsqu'un nouvel appel d'opérateur approprié se produit:
int main() {
// the object that s points to has dynamic storage
// duration
string *s = new string;
// pass a pointer pointing to the object around.
// the object itself isn't touched
foo(s);
delete s;
}
void foo(string *s) {
cout << s->size();
}
Sa durée de vie ne prend fin que lorsque vous appelez delete pour eux. Si vous oubliez cela, ces objets ne terminent jamais leur vie. Et les objets de classe qui définissent un constructeur déclaré par l'utilisateur ne verront pas leurs destructeurs appelés. Les objets ayant une durée de stockage dynamique nécessitent une gestion manuelle de leur durée de vie et de la ressource mémoire associée. Des bibliothèques existent pour faciliter leur utilisation. Un garbage collection explicite pour des objets particuliers peut être établi à l'aide d'un pointeur intelligent:
int main() {
shared_ptr<string> s(new string);
foo(s);
}
void foo(shared_ptr<string> s) {
cout << s->size();
}
Vous n'avez pas à vous soucier d'appeler delete: le ptr partagé le fait pour vous, si le dernier pointeur qui fait référence à l'objet sort de la portée. Le ptr partagé lui-même a une durée de stockage automatique. Donc , sa durée de vie est gérée automatiquement, ce qui permet de vérifier si elle doit supprimer l'objet pointu dynamique dans son destructor. Pour plus d'informations sur shared_ptr, consultez les documents boost: http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/shared_ptr.htm