Pourquoi ne puis-je pas déclarer une référence à un object mutable? (“La référence ne peut pas être déclarée mutable”)

Disons que nous avons un test.cpp comme suit:

 class A; class B { private: A mutable& _a; }; 

Compilation:

 $> gcc test.cpp test.cpp:6:20: error: reference '_a' cannot be declared 'mutable' [-fpermissive] 

Mon gcc:

 $> gcc --version gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

Pourquoi?

Il n’y a aucune raison d’avoir un membre de référence mutable. Pourquoi? Les fonctions de membre const pouvant modifier l’object référencé par un membre de la classe:

 class B { public: B(int var) : n(var) {}; void Set(int val) const { n = val; } //no error void SetMember(int val) const { m = val; } //error assignment of member `B::m' in read-only structure protected: int& n; int m; }; 

Les références ne peuvent être atsortingbuées que lors de la construction d’un object et ne peuvent pas être modifiées par la suite. Ainsi, les rendre mutable n’aurait aucun sens, c’est pourquoi la norme l’interdit.

Selon la norme: [7.1.1 paragraphe 8]:

“Le spécificateur mutable peut être appliqué uniquement aux noms des membres de données de classe (9.2) et ne peut pas être appliqué aux noms déclarés const ou static, ni aux membres de référence.”

C’est donc illégal.

Cela pourrait vous faire perdre la tête, mais une référence n’est jamais modifiable (il est impossible de faire référence à un autre object) et la valeur référencée est toujours modifiable (sauf si vous avez une référence à la constante):

 #include  struct A { int& i; A(int& n): i(n) {} void inc() const { ++i; } }; int main() { int n = 0; const A a(n); a.inc(); std::cout << n << '\n'; } 

Une méthode const signifie qu'un qualificatif const de niveau supérieur est ajouté aux membres. Pour une référence, cela ne fait rien (= int & const a; ), mais pour un pointeur, c'est le pointeur, pas la pointee const (= int* const p , pas const int* p; ).