Historique de la question :
La liste d'initialisation a été introduite dans C++ pour optimiser et assurer une initialisation correcte des membres de classe avant l'exécution du corps principal du constructeur. Cela provient de l'expérience avec C et C++ : il est impossible d'initialiser les membres constants et les références dans le corps du constructeur, uniquement dans la liste.
Problème :
En tentant d'initialiser de tels membres dans le corps du constructeur plutôt qu'à partir de la liste d'initialisation, une erreur de compilation se produira. Ignorer la liste entraîne également un double appel d'initialisation pour les objets membres, ce qui impacte les performances, surtout avec des constructeurs initialisateurs complexes.
Solution :
Il est optimal de déclarer et d'initialiser les membres de la classe via une liste d'initialisation, surtout s'il s'agit de constantes (const) ou de références (&). La liste d'initialisation est utilisée AVANT l'exécution du corps du constructeur, lorsque les membres de la classe sont en cours de construction.
Exemple de code :
class Exemple { const int valeur; int& ref; public: Exemple(int v, int& r) : valeur(v), ref(r) { /* corps du constructeur */ } };
Caractéristiques clés :
Que se passe-t-il si l'on change l'ordre des membres de la classe et leur initialisation dans la liste ?
L'initialisation se produit toujours dans l'ordre de déclaration des membres dans la classe, et non dans l'ordre dans lequel ils ont été écrits dans la liste d'initialisation. Si des membres dépendants sont initialisés "dans le mauvais ordre", cela peut conduire à un accès à une mémoire non initialisée.
Exemple de code :
class Foo { int x; int y; Foo() : y(2), x(y) {} // x sera initialisé en PREMIER, avec la valeur de y non initialisée }
Peut-on initialiser un membre const d'une classe dans le corps du constructeur ?
Non. Cela entraînera une erreur de compilation. Seulement via une liste d'initialisation.
Que se passe-t-il si l'on n'initialise pas un membre référence ?
Si un membre référence n'est pas initialisé, une erreur de compilation surviendra, car la référence doit être "liée" à un objet lors de sa création et ne peut pas être changée par la suite.
Dans une classe de stockage de paramètres, une const std::string et une référence sont utilisées, et la tentative d'initialiser ces membres se fait dans le corps du constructeur, ce qui entraîne une erreur du compilateur ou des données non initialisées.
Avantages : Le novice a appris de l'erreur, distinguant la construction de l'affectation.
Inconvénients : Erreur de compilation, impossibilité d'utiliser la classe, risques d'erreurs inattendues lors de l'initialisation des objets.
La constante et la référence sont correctement initialisées via la liste d'initialisation. Tout le code d'initialisation complexe est centralisé dans la liste, ce qui augmente la lisibilité et prévient les erreurs.
Avantages : Initialisation sécurisée et correcte des membres de classe, haute lisibilité, absence de fuites ou de UB.
Inconvénients : Une logique d'initialisation complexe peut survenir, dont une partie peut ne pas être facile à tester sans code supplémentaire.