Un type de référence doit-il être initialisé dans la liste d’initialisation du constructeur?

À titre d’exercice personnel, j’ai écrit ce code simple:

#include  int gIndex = 3; template  class Array { public: explicit Array(int size); T& operator[](int i) { return m_data[i]; } T operator[](int i) const { return m_data[i]; } T getAnchorPoint() const { return m_data[m_anchor]; } private: T* m_data; int m_size; int& m_anchor; }; template  Array::Array(int size) : m_size(size), m_data(new T[size]) { memset(m_data, 0, size*sizeof(T)); m_anchor = gIndex; } int main() { Array a(10); return 0; } 

J’ai une erreur de compilation qui dit:

error C2758: 'Array::m_anchor' : must be initialized in constructor base/member initializer list

Ce n’est jamais arrivé, ce qui m’amène à poser cette question:

Un type de référence de membre de classe doit-il être initialisé dans la liste d’initialisation du constructeur?

Si oui, pourquoi? Cela at-il un lien avec le fait qu’un type de référence ne peut jamais être réaffecté?

Y a-t-il plus de types à initialiser dans la liste d’initialisation du constructeur?

Un type de référence membre de classe doit-il être initialisé dans la liste d’initialisation du constructeur?

Oui.

Si oui, pourquoi? Cela at-il un lien avec le fait que le type de référence ne peut jamais être réaffecté?

Cela fait partie de la raison. L’autre partie est due au fait qu’une référence doit être initialisée et qu’elle n’a pas de constructeur par défaut.

Y a-t-il plus de types à initialiser dans la liste d’initialisation du constructeur?

Tout type qui n’a pas d’opérateur d’affectation (copier ou déplacer) ou de constructeur par défaut. Cela inclut évidemment (sans toutefois s’y limiter) les membres const , car ils ne peuvent pas être modifiés une fois qu’ils ont été construits.


En règle générale, vous devriez (presque) toujours préférer initialiser vos membres dans la liste d’initialisation du constructeur: pourquoi gaspille-t-il d’abord la construction par défaut d’un object, puis l’assignation à celui-ci (si cela est même possible), il correctement en premier lieu?

Un type de référence de membre de classe doit-il être initialisé dans la liste d’initialisation du constructeur?

Oui.

Cela at-il un lien avec le fait qu’un type de référence ne peut jamais être réaffecté?

Oui, plus le fait qu’il n’y ait pas de construction “nulle” ou par défaut pour une référence. C’est un alias pour un autre object, et il doit être lié à lui dès le départ. Vous ne pouvez pas faire ceci (cela ne fait pas partie d’une définition de classe):

 int main() { int& iref; // ERROR int i = 42; int& iref2 = i; // OK } 

parce que iref doit alias quelque chose .

 Must any class-member reference type be initialized in the constructor initialization list? 

Oui, nous devrions toujours utiliser la liste d’initialisation pour initialiser les membres de référence d’une classe.

 If so, why? Is that related somehow to the fact that a reference type can never be reassigned? 

Un constructeur a deux phases à savoir l’initialisation et le calcul. Ainsi, même si vous n’utilisez pas la liste d’initialisation pour un compilateur de membre de données l’initialisera avec une valeur aléatoire. Et dans la phase de calcul qui commence généralement par le ‘{‘ du corps du constructeur, si vous effectuez une affectation, le compilateur se plaindra car le membre de référence était déjà initialisé. Ainsi, votre seule chance d’initialiser ce membre est la liste d’initialisation du constructeur.

 Are there more types that must be initialized in constructor initialization list? 

Oui, les membres de données const sont l’autre type pour lequel vous avez besoin d’une liste d’initialiseurs.