Pourquoi les membres const peuvent-ils être modifiés dans un constructeur?

Je suis curieux de savoir pourquoi les membres const peuvent être modifiés dans le constructeur.

Existe-t-il une règle standard dans l’initialisation qui remplace la “const-ness” d’un membre?

struct Bar { const int b = 5; // default member initialization Bar(int c):b(c) {} }; Bar *b = new Bar(2); // Problem: Bar::b is modified to 2 // was expecting it to be an error 

Des idées?

Ce n’est pas une modification (ou une affectation) mais une initialisation . par exemple

 struct Bar { const int b = 5; // initialization (via default member initializer) Bar(int c) :b(c) // initialization (via member initializer list) { b = c; // assignment; which is not allowed } }; 

Le membre de données const ne peut pas être modifié ou atsortingbué, mais il peut (et doit) être initialisé via la liste d’initialisation de membre ou l’initialiseur de membre par défaut.

Si l’initialiseur de membres par défaut et l’initialiseur de membres sont tous deux fournis sur le même membre de données, l’initialiseur de membres par défaut sera ignoré. C’est pourquoi b->b est initialisé avec la valeur 2 .

Si un membre possède un initialiseur de membres par défaut et apparaît également dans la liste d’initialisation des membres dans un constructeur, l’initialiseur de membres par défaut est ignoré.

Par contre, l’initialiseur de membres par défaut ne prend effet que lorsque le membre de données n’est pas spécifié dans la liste d’initialisation des membres. par exemple

 struct Bar { const int b = 5; // default member initialization Bar(int c):b(c) {} // b is initialized with c Bar() {} // b is initialized with 5 }; 

En ajoutant à la réponse de songyuanyao, si vous voulez un membre de données const que vous ne pouvez pas initialiser dans un constructeur, vous pouvez rendre le membre static :

 struct Bar { static const int b = 5; // static member initialization Bar(int c) :b(c) // Error: static data member can only be initialized at its definition { b = c; // Error: b is read-only } }; 

En C ++ 17, vous pouvez améliorer cela en le rendant inline :

 struct Bar { inline static const int b = 5; // static member initialization Bar(int c) :b(c) // Error: static data member can only be initialized at its definition { b = c; // Error: b is read-only } }; 

De cette façon, vous n’aurez pas de problèmes avec ODR.

Quand tu fais:

 struct Bar { const int b = 5; // default member initialization ... }; 

Vous dites au compilateur de le faire avec le constructeur par défaut:

 ... Bar() : b(5) {} ... 

Indépendamment de si vous avez fourni le constructeur par défaut ou non. Lorsque vous fournissez le constructeur par défaut et l’assignation initiale, vous remplacez le code d’atsortingbution par défaut du compilateur (c.-à-d. b(5) ). L’initialisation / affectation par défaut à la déclaration est utile lorsque vous avez plusieurs constructeurs et que vous pouvez ou non affecter les membres const dans tous les constructeurs:

 ... Bar() = default; // b=5 Bar(int x) : b(x) // b=x Bar(double y) : /*other init, but not b*/ // b=5 ...