2010-01-18 16 views
10

Come funziona il seguente codice in C++? È logico?Inizializzazione letterale per riferimenti const

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

Perché C++ permette l'inizializzazione letterale per i riferimenti const quando lo stesso non è consentito per i riferimenti non-const? Es .:

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

Ciò può essere spiegato dal fatto che, un riferimento non const può essere utilizzato per modificare il valore della variabile a cui fa riferimento. Quindi, C++ non consente un riferimento non const a una variabile const.

Potrebbe essere una possibile spiegazione? C++ non consente:

int &ref = 7; 

perché non è logico, ma:

const int &ref = 7; 

è quasi equivalente a:

const int val = 7; 

inizializzazione così letterale è consentito per le variabili const.

P.S .: Attualmente sto studiando il Primer C++ di Lippman.

risposta

7

modo da poter scrivere codice come questo:

void f(const string & s) { 
} 

f("foobar"); 

Anche se a rigor di termini ciò che sta realmente accadendo qui non è letterale essere vincolato ad un riferimento const - invece un oggetto stringa temprary si crea:

string("foobar"); 

e questa stringa senza nome è associata al riferimento.

Si noti che in realtà è piuttosto insolito creare variabili di riferimento senza parametri come si fa - lo scopo principale dei riferimenti è di fungere da parametri di funzione e valori di ritorno.

6

continui riferimenti possono essere inizializzati con letterali e provvisori, perché si può banalmente trasformarli alle variabili esplicite:

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

Oppure, quando la durata non è rinnovato, come ad esempio un parametro di funzione:

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

(notare il blocco esplicito in questo caso.)

Mentre è possibile fare qualcosa di simile nel caso non costante, questo non è solo consentito in currenct C++. C++ 0x (lo standard successivo), tuttavia, avrà riferimenti di valore r.


Se non fosse chiaro, ref + 6 dal codice crea un oggetto temporaneo, che è possibile visualizzare come:

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; 

Questo può aiutare a capire/visualizzare ciò che sta accadendo, ma si dovrebbe non scrivere codice reale come questo.Inoltre ho usato i doppi nomi di sottolineatura per illustrare quei nomi sono dettagli di implementazione (usati dal compilatore) e non dovrebbero essere usati da voi. Qualsiasi nome che contenga caratteri di sottolineatura adiacenti è riservato all'implementazione di C++.

+0

+1. Ma penso che il tuo secondo esempio verrebbe trasformato in { string __internal_unique_name ("foobar"); f (___name_unique_name); } – mmmmmmmm

+0

@rstevens: non importa: la conversione non deve essere esplicita, nel qual caso sono uguali. –

2

Il codice si riduce alla regola standard C++ in cui la durata di un valore temporaneo è associata alla durata del riferimento const a cui è assegnato. Vedere l'articolo articolo GotW #88: A Candidate For the “Most Important const” per ulteriori dettagli.

Ad esempio, l'implementazione di ScopeGuard, descritta da Alexandrescu e Marginean nell'articolo "Generic: Change the Way You Write Exception-Safe Code — Forever" del Dr. Dobbs dipende da questo comportamento.

Problemi correlati