Riferimenti

 


 

Costruzione di una variabile mediante copia

 

Riassumiamo i casi in cui una variabile (o più in generale un oggetto) viene costruita (creata) mediante copia di una variabile esistente dello stesso tipo:

 


 

Cosa sono i riferimenti ?

 

In C++ i riferimenti sono variabili introdotte dall'operatore di dichiarazione :

&

Il loro significato è quello di occupare la stessa memoria delle variabili a cui si riferiscono (in altre parole sono degli alias di altre variabili).

Si definiscono come nel seguente esempio:   int & ref = var;
(dove var è una variabile di tipo int precedentemente definita, oppure una qualunque espressione che restituisce un l-value di tipo int) la variabile ref è un riferimento a var: qualsiasi modifica apportata a var si ritrova in ref (e viceversa). I tipi di ref e var devono coincidere, non è ammesso il
casting in nessun caso (anche quando i tipi sono in pratica gli stessi, come int e long). L'insieme int & assume la connotazione di un nuovo tipo: il tipo di riferimento a int.
Nota
: nelle definizioni multiple & va ripetuto: in altre parole, l'operatore di dichiarazione & va considerato, dal punto di vista sintattico, un prefisso dell'identificatore e non un suffisso del tipo.

Va da sé che i riferimenti vanno sempre inizializzati. L'inizializzazione, tuttavia, non comporta la costruzione di una nuova variabile mediante copia, in quanto, per il programma, si tratta sempre della stessa variabile (la differenza fra i nomi "scompare" dopo la compilazione).

E' anche possibile dichiarare un riferimento con lo specificatore const :    
                const int & ref = var;
si può sempre modificare var (e di conseguenza resta modificato ref), ma non si può modificare direttamente ref, che per questo viene anche detto alias di riferimento a sola lettura.

I riferimenti dichiarati const si possono anche inizializzare con un non l-value (e non necessariamente dello stesso tipo, purchè convertibile implicitamente). Es.:
        int & ref = var+1;        non ammesso: var+1 non è un l-value
         const int & ref = var+1;        ammesso, anche se var non è int

Ciò è possibile perchè in questo caso il programma crea una variabile temporanea di tipo int (chiamiamola temp) che inizializza con var+1 (dopo aver convertito, se necessario, il tipo di var in int) e poi definisce:  
        const int & ref = temp;
La variabile temp persiste nello stesso ambito di ref, ma non è accessibile e quindi in questo caso ref non può più cambiare anche se cambia var.

 


 

Comunicazione per "riferimento" fra programma e funzione

  

L'uso più frequente dei riferimenti si ha nelle comunicazioni fra funzione e programma chiamante. Infatti, mentre in C il passaggio degli argomenti e del valore di ritorno avviene sempre e soltanto by value, in C++ può avvenire anche by reference (per riferimento).

 

  Da programma chiamante a funzione

Un argomento passato a una funzione può essere dichiarato come riferimento:

funz(int& num)

in questo caso l'argomento è passato by reference, cioè non ne viene costruita una copia, ma la variabile num é un alias di riferimento della sua corrispondente nel programma chiamante.

Ne consegue che ogni modifica apportata a num in funz viene effettuata anche nel programma chiamante.
Es.:         funzione: funz(int& a)   { ..... a = a+1; .... }
prog. chiamante:       int b = 0; ...... funz(b); .....

alla fine in b si ritrova il valore 1

In base alle regole enunciate nel paragrafo precedente, il valore passato alla funzione deve essere un l-value ed esattamente dello stesso tipo del corrispondente argomento dichiarato nella funzione (a meno che non venga dichiarato const, nel qual caso non ci sono restrizioni, purchè sia ammessa la conversione di tipo implicita).

 

  Da funzione a programma chiamante

Anche il valore di ritorno restituito da una funzione può essere dichiarato come riferimento.
Es.:       nel programma chiamante:       ..... funz( ); .......
nella funzione: int& funz( ) { ...... return b; .... }

anche questa volta il valore è passato by reference, cioè non ne viene costruita una copia, ma nel programma chiamante viene utilizzato direttamente il riferimento al valore b restituito da funz (per le note regole b deve essere un l-value, a meno che il valore di ritorno non sia dichiarato const) .
In questo caso però, onde evitare errori in esecuzione, é necessario che b sopravviva a funz; ciò é possibile soltanto in uno dei seguenti tre casi:

Il valore di ritorno è un l-value (se non è dichiarato const). Questo significa che la chiamata di una funzione che ritorna un valore by reference può essere messa a sinistra di un'operazione di assegnazione !!!
Ciò è possibile solo in
C++ !

[p24]

 


 

Torna all'Indice