Une liste d'initialisation de constructeur commence par un deux-points, suivie d'une liste de membres de données séparés par des virgules, chaque membre de données étant suivi d'un initialiseur entre parenthèses. Par exemple :
class CExample {
public:
int a;
float b;
//构造函数初始化列表
CExample(): a(0),b(8.8)
{}
//构造函数内部赋值
CExample()
{
a=0;
b=8.8;
}
};
Dans l'exemple ci-dessus, les résultats des deux constructeurs sont identiques. Le constructeur ci-dessus (celui qui utilise la liste d'initialisation) initialise explicitement les membres de la classe ; tandis que le constructeur qui n'utilise pas la liste d'initialisation attribue des valeurs aux membres de la classe, sans initialisation explicite.
L'initialisation et l'affectation ont peu d'importance pour les membres de types intégrés, donc l'un ou l'autre des constructeurs ci-dessus fonctionne. Pour les variables membres de types non intégrés, afin d'éviter une double construction, il est recommandé d'utiliser la liste d'initialisation du constructeur de classe. Mais parfois, un constructeur avec une liste d'initialisation est requis :
- 1. Le type du membre estune classe sans constructeur par défaut. Si aucun initialiseur explicite n'est fourni, le compilateur utilise implicitement le constructeur par défaut du type du membre. Si la classe n'a pas de constructeur par défaut, la tentative du compilateur d'utiliser le constructeur par défaut échouera.membres const
- 2.membres constoumembres de type référence. Parce que les objets const ou les types référence ne peuvent être qu'initialisés, et non se voir affecter une valeur.
Que signifie initialiser des membres de données par rapport au fait de leur affecter des valeurs ? Quelle est la différence ?
Tout d'abord, classons les membres de données par type et expliquons chaque cas :
- 1.Types de données intégrés, types composés (pointeurs, références)- Le faire dans la liste d'initialisation des membres ou dans le corps du constructeur est identique en termes de performance et de résultat.
- 2.Types définis par l'utilisateur (types de classe)- Les résultats sont identiques, mais il existe une grande différence de performance. Parce que les objets membres de données de type classe sont déjà construits avant d'entrer dans le corps de la fonction, c'est-à-dire que le travail de construction est effectué dans la liste d'initialisation des membres, en appelant le constructeur. Après être entré dans le corps de la fonction, ce qui est fait est l'affectation de valeurs aux objets de classe déjà construits, ce qui nécessite d'appeler un opérateur d'affectation de copie pour terminer (s'il n'est pas fourni, le comportement d'affectation membre à membre par défaut fourni par le compilateur est utilisé).
Notes :
Ordre d'initialisation des membres dans la liste d'initialisation :
C++ initialise les membres de classe dans l'ordre dans lequel ils sont déclarés, et non dans l'ordre dans lequel ils apparaissent dans la liste d'initialisation.
class CMyClass {
CMyClass(int x, int y);
int m_x;
int m_y;
};
CMyClass::CMyClass(int x, int y) : m_y(y), m_x(m_y)
{
};
Vous pourriez penser que le code ci-dessus effectuera d'abord m_y=I, puis m_x=m_y, et qu'enfin ils auront la même valeur. Mais le compilateur initialise m_x en premier, puis m_y, car ils sont déclarés dans cet ordre. Par conséquent, m_x aura une valeur imprévisible. Il existe deux façons d'éviter cela : la première est de toujours déclarer les membres dans l'ordre dans lequel vous souhaitez qu'ils soient initialisés ; la seconde est, si vous décidez d'utiliser une liste d'initialisation, de toujours lister les membres dans l'ordre dans lequel ils sont déclarés. Cela aidera à éliminer la confusion.
Adresse d'origine : http://www.cnblogs.com/BlueTzar/articles/1223169.html