La norme ISO C++03 fait autorité en la matière :
Une structure POD est une classe agrégée qui n'a pas de membres de données non statiques de type structure non POD, union non POD (ou tableau de ces types) ou référence, et qui n'a pas d'opérateur d'affectation de copie défini par l'utilisateur ni de destructeur défini par l'utilisateur. De même, une union POD est une union agrégée qui n'a pas de membres de données non statiques de type non-POD-struct, non-POD-union (ou tableau de tels types) ou référence, et qui n'a pas d'opérateur d'affectation de copie défini par l'utilisateur ni de destructeur défini par l'utilisateur. Une classe POD est une classe qui est soit une structure POD, soit une union POD.
Les types arithmétiques (3.9.1), les types énumération, les types pointeur et les types pointeur sur membre (3.9.2), ainsi que les versions qualifiées cv de ces types (3.9.3) sont collectivement appelés types scalaires. Les types scalaires, les types POD-struct, les types POD-union (clause 9), les tableaux de ces types et les versions qualifiées cv de ces types (3.9.3) sont collectivement appelés types POD.
L'initialisation à zéro d'un objet de type T signifie :
- si T est un type scalaire (3.9), l'objet est mis à la valeur 0 (zéro) convertie en T ;
- si T est un type de classe non syndiqué, chaque membre de données non statique et chaque sous-objet de la classe de base est zéro initialisation est initialisé à zéro ;
- si T est un type union, le premier membre nommé de l'objet est initialisé à zéro ;
- si T est un type de tableau, chaque élément est initialisé à zéro ;
- si T est un type de référence, aucune initialisation n'est effectuée.
Initialiser par défaut un objet de type T signifie :
- si T est un type de classe non POD (clause 9), le constructeur par défaut de T est appelé (et l'initialisation est mal formée si T n'a pas de constructeur par défaut accessible) ;
- si T est un tableau, chaque élément est initialisé par défaut ;
- sinon, l'objet est initialisé à zéro.
Initialiser un objet de type T par une valeur signifie :
- si T est un type de classe (clause 9) avec un constructeur déclaré par l'utilisateur (12.1), alors le constructeur par défaut de T est appelé (et l'initialisation est mal formée si T n'a pas de constructeur par défaut accessible) ;
- si T est un type de classe non syndiqué sans constructeur déclaré par l'utilisateur, alors chaque membre de données non statique et chaque composant de classe de base de T est initialisé par une valeur ;
- si T est un type de tableau, chaque élément est initialisé par une valeur ;
- sinon, l'objet est initialisé à zéro
Chaque objet de durée de stockage statique doit être initialisé à zéro au démarrage du programme avant toute autre initialisation. [Note : dans certains cas, une initialisation supplémentaire est effectuée ultérieurement].
Un objet dont l'initialisateur est un ensemble vide de parenthèses, c'est-à-dire (), doit être initialisé par une valeur.
Si aucun initialisateur n'est spécifié pour un objet, et que l'objet est d'un type de classe (ou d'un tableau de ce type) non POD (éventuellement qualifié cv), l'objet est initialisé par défaut ; si l'objet est d'un type qualifié const, le type de classe sous-jacent doit avoir un constructeur par défaut déclaré par l'utilisateur. Dans le cas contraire, si aucun initialisateur n'est spécifié pour un objet non statique, l'objet et ses sous-objets, le cas échéant, ont une valeur initiale indéterminée ; si l'objet ou l'un de ses sous-objets est de type const-qualifié, le programme est mal formé.
Pour votre exemple, int
est bien un type POD (c'est un type arithmétique), et donc un local ou un champ de type int
en l'absence d'initialisateur, aura une valeur indéterminée. Pour les Foo
En gros, s'il n'a pas de constructeur et que tous ses membres sont des types POD, il est lui-même un type POD et aucune initialisation n'a lieu. Dans le cas contraire, le constructeur par défaut est appelé. Même dans ce cas, cela ne signifie pas que membres sont initialisés - les règles sont récursives, de sorte que les membres POD d'un type non POD ne seront pas initialisés à moins que le constructeur de ce type ne le fasse spécifiquement (dans sa liste d'initialisateurs).
Les variables et champs statiques seront dans tous les cas initialisés à zéro. Notez que ceci s'applique également aux non-PODs - ce qui signifie qu'une variable statique d'un type de classe est garantie d'avoir tous les champs définis récursivement à (T)0
avant même l'exécution de son constructeur.
Une astuce pratique pour initialiser par défaut n'importe quel type de POD agrégé est d'utiliser {}
dans l'initialisateur - notez que cela fonctionne aussi bien avec les structures qu'avec les tableaux :
char s[10] = {}; // all elements default-initialized
Foo foo = {}; // all fields recursively default-initialized