Historique de la question :
Dans le C++ classique, les membres de classe étaient initialisés uniquement dans la liste d'initialisation du constructeur. Avec C++11, il est devenu possible de spécifier des valeurs par défaut directement dans la déclaration au sein de la classe (initialisateurs de membres) pour améliorer la lisibilité et la sécurité du code.
Problème :
Il existe plusieurs façons de définir une valeur pour un membre de classe : directement dans la déclaration (in-class), via la liste d'initialisation du constructeur et déjà dans le corps du constructeur. Différentes méthodes ont un impact sur les performances et la sémantique ; une mauvaise compréhension peut conduire à des copies inutiles ou à des destructeurs par défaut, à des erreurs avec des constantes et des références.
Solution :
class MyClass { int x = 42; };
class MyClass { const int y; MyClass(int val) : y(val) {} // sinon — erreur de compilation };
class MyClass { std::string s; MyClass() { s = "hello"; } // D'abord défaut, puis affectation };
Caractéristiques clés :
Quel sera l'ordre d'initialisation des membres : dans l'ordre dans lequel ils sont déclarés dans la classe, ou dans l'ordre de la liste d'initialisation ?
L'ordre d'initialisation est toujours celui dans lequel les membres sont déclarés dans la classe, et non pas dans l'ordre de la liste d'initialisation. Une violation de l'ordre est dangereuse pour les membres dépendants.
class A { int x = 1; int y = 2; A() : y(10), x(20) {} }; // x est initialisé avant y, malgré l'ordre dans la liste
Peut-on initialiser un membre constant à l'intérieur du corps du constructeur, s'il n'a pas été initialisé dans la liste ?
Non. Les constantes ne sont initialisées que dans la liste d'initialisation. Une affectation dans le corps du constructeur est une erreur de compilation.
Que se passe-t-il si l'on définit une valeur par défaut pour un membre directement dans la classe via un initialisateur in-class et que l'on la redéfinit dans la liste d'initialisation du constructeur ?
La valeur de la liste d'initialisation du constructeur sera utilisée. La valeur par défaut n'est utilisée que si la liste ne spécifie rien.
class C { int x = 10; C() : x(20) {} // x sera égal à 20 };
La classe travaille avec un fichier. Le fichier est déclaré comme std::ofstream et est initialisé dans le corps du constructeur. Danger : lors du constructeur par défaut, un std::ofstream invalide peut être créé, ce qui entraîne des erreurs lors de l'utilisation du fichier.
Avantages :
Inconvénients :
Le fichier est initialisé dans la liste d'initialisation, ce qui empêche l'utilisation erronée du fichier dans un état invalide, tandis que les membres avec des données par défaut utilisent l'initialisateur in-class.
Avantages :
Inconvénients :