2010-01-18 5 views
10

Comment fonctionne le code suivant en C++? Est-ce logique? Pourquoi le C++ autorise-t-il l'initialisation littérale pour les références const quand la même chose n'est pas autorisée pour les références non-const? C12. .: par exemple Initialisation littérale pour les références const

const int days_of_week = 7; 
int &dof = days_of_week; //error: non const reference to a const object 

Ceci peut être expliqué par le fait que, peut être utilisé une référence non-const pour modifier la valeur de la variable, il fait référence. Par conséquent, C++ n'autorise pas une référence non-const à une variable const.

Est-ce que cela pourrait être une explication? C++ ne permet pas:

int &ref = 7; 

Parce que ce n'est pas logique, mais:

const int &ref = 7; 

est presque équivalent à:

const int val = 7; 

initialisation Donc littéral est autorisée pour les variables const.

P.S.: J'étudie actuellement l'amorce C++ de Lippman.

Répondre

7

Vous pouvez écrire du code comme ceci:

void f(const string & s) { 
} 

f("foobar"); 

Bien que strictement parlant ce qui se passe réellement ici n'est pas le littéral étant lié à une référence const - au lieu d'un objet chaîne temprary est créé:

string("foobar"); 

et cette chaîne sans nom est liée à la référence.

Notez qu'il est assez inhabituel de créer des variables de référence sans paramètre comme vous le faites - l'objectif principal des références est de servir de paramètres de fonction et de valeurs de retour.

6

références constantes peuvent être initialisés avec littéraux et temporaire parce que vous pouvez trivialement les transformer à des variables explicites:

int const& ans = 42; 
// tranformed: 
int __internal_unique_name = 42; 
int const& ans = __internal_unique_name; 

Ou quand la durée de vie est pas prolongée, comme un paramètre de fonction:

f("foobar"); 
// transformed: 
{ 
    string __internal_unique_name = "foobar"; 
    f(__internal_unique_name); 
} 

(Notez le bloc explicite dans ce cas.)

Bien qu'il soit possible de faire quelque chose de similaire dans le cas non constant, ce n'est tout simplement pas autorisé en currenct C++. C++ 0x (le prochain standard), cependant, aura des références de valeur r.


Si on ne savait pas, ref + 6 à partir de votre code crée un objet temporaire, que vous pouvez visualiser comme:

int const& ref = int(9); 
int const& another_ref = int(ref + 6); 

// transformed: 
int __A = 9; 
int const& ref = __A; 
int __B = ref + 6; 
int const& another_ref = __B; 

Cela peut vous aider à comprendre/visualiser ce qui se passe, mais vous devez pas écrire de vrai code comme ça.J'ai également utilisé des doubles noms de soulignement pour illustrer ces noms qui sont des détails d'implémentation (utilisés par le compilateur) et ne devraient pas être utilisés par vous. Tout nom qui contient des traits de soulignement adjacents est réservé à l'implémentation C++.

+0

+1. Mais je pense que votre deuxième exemple serait transformé en { chaîne __internal_unique_name ("foobar"); f (__ internal_unique_name); } – mmmmmmmm

+0

@rstevens: ce n'est pas grave: la conversion ne doit pas être explicite, auquel cas ils sont identiques. –

2

Votre code se résume à la règle standard C++ où la durée de vie d'une valeur temporaire est liée à la durée de vie de la référence const à laquelle elle est affectée. Voir l'article GoTWGotW #88: A Candidate For the “Most Important const” pour plus de détails. Par exemple, l'implémentation ScopeGuard, décrite par Alexandrescu et Marginean dans l'article Dr. Dobbs "Generic: Change the Way You Write Exception-Safe Code — Forever" dépend de ce comportement.