Differences

This shows you the differences between two versions of the page.

Link to this comparison view

appunti3s:cenni_ai_references [2018/04/25 07:55] (current)
Line 1: Line 1:
 +====== Premessa ======
 +Sia nel linguaggio C che in C++ si può effettuare il passaggio di parametri esclusivamente //per valore//, cioè copiando il contenuto delle variabili indicate tra parentesi.
 +Vedere esempio [[appunti3s:​programmi_procedurali#​passaggio_per_valore]].
 +Questo impedisce di effettuare delle modifiche sui //parametri effettivi// della funzione.
 +<​code>​int triplicare(int x)
 +{
 + ​x=x*3;​ // modifica solo la var. locale x
 + ​return x;
 +}
 +</​code>​
 +
 +Tuttavia, se al posto dei tradizionali tipi di dato (come //int//) si usano i puntatori (come //int*//), la funzione riesce ad accedere e a modificare anche i //parametro effettivi//​. ​
 +<​code>​int triplicare(int* p)
 +{
 + ​*p=*p*3; ​ // modifica anche la variabile puntata da p
 + ​return *p;
 +}
 +</​code>​
 +Come si può notare dal secondo esempio, questo appesantisce il codice costringendo ad aggiungere l'​operatore di deferimento //*// (l'​asterisco) davanti al puntatore //p//.
 +
 +I //​references//,​ invece, hanno la stessa "​forza"​ dei puntatori, ma una sintassi molto semplice.
 +
 +====== References ======
 +
 +Quando una funzione ha come //parametro formale// un reference, al suo interno NON viene crea una nuova variabile locale, ma si lavora proprio sul //parametro effettivo// usando il parametro formale come il suo soprannome temporaneo.
 +<​code>​void triplicare(int&​ x); </​code>​
 +La dichiarazione si legge in questo modo:
 +la funzione accetta come argomento un //reference a...// intero.
 +
 +Purtroppo il simbolo //&//, usato in un altro luogo, possiede anche altri significati,​ completamente diversi. Dentro un'​espressione logica può significare operatore //AND binario//, oppure scirtto davanti al nome di una variabile, operatore //indirizzo di//. 
 +Il reference al momento della sua dichiarazione __deve__ essere sempre inizializzato,​ infatti non si può usare un soprannome senza dire a chi corrisponde quell'​alias... Al contrario dei puntatori, i reference, una volta inizializzati come alias ad un oggetto, non possono diventare l'​alias di niente altro.
 +
 +<file cpp 20.cpp>
 +// Questo programma è stato scritto da Fabio.
 +// Serve a calcolare il triplo di un numero.
 +
 +#include <​iostream>​
 +
 +// questo modo di passare il parametro ​
 +// non crea una copia locale
 +// questa funzione e' di tipo void, cioe' non restituisce nulla (manca return)
 +
 +void triplicare(int&​ x) 
 +{
 +  x = 3*x;
 +}
 +
 +int main ()
 +{
 +  int mioNumero,​mioTriplo;​
 +
 +  std::cout << "Per favore scrivi un numero intero: ";
 +  std::cin >> mioNumero;
 +  ​
 +  triplicare(mioNumero);​ // chiamata della funzione che modifica il mioNumero
 +  ​
 +  std::cout << "il triplo vale " << mioNumero << "​.\n";​
 +  return 0;
 +}
 +</​file>​
 +
 +====== references costanti ======
 +
 +Premettendo //const// davanti ad un reference si __impedisce__ di modificare il //parametro effettivo//​. L'​effetto è simile al classico passaggio per valore, ma con la differenza che invece di creare una copia del parametro effettivo, in pratica si copia solo il suo indirizzo.
 +
 +Questo è utilizzato soprattutto quando il parametro effettivo è un "​oggetto"​ (difficile da copiare o di notevoli dimensioni). ​
 +
 +<file cpp 21.cpp>
 +// Questo programma è stato scritto da Fabio.
 +
 +#include <​iostream>​
 +
 +// questo modo di passare il parametro ​
 +// passa l'​indirizzo di memoria di questo parametro
 +// il termine const evita modifiche indesiderate al parametro.
 +
 +// NON creando una nuova variabile x, risparmio memoria!
 +// x è solo il soprannome temporaneo che viene dato a mioNumero
 +
 +int triplicare(const int& x)  ​
 +{
 + ​return 3*x;
 +}
 +
 +int main ()
 +{
 +  int mioNumero;
 +
 +  std::cout << "Per favore scrivi un numero intero: ";
 +  std::cin >> mioNumero;
 +  ​
 +  std::cout << "il triplo di " << mioNumero
 +            << " vale " << triplicare(mioNumero) "​.\n";​
 +  return 0;
 +}
 +</​file>​
 +
 +<file cpp 22.cpp>
 +// Questo programma è stato scritto da Fabio.
 +
 +// Serve a calcolare il triplo di un numero.
 +// I reference sono utili per risparmiare memoria
 +// anche sul tipo restituito dalla funzione
 +// basta aggiungere UN SECONDO reference (sempre preceduto da un const)
 +
 +#include <​iostream>​
 +
 +const int& triplicare(const int& x)  ​
 +{
 + ​return 3*x;
 +}
 +
 +int main ()
 +{
 +  int mioNumero;
 +
 +  std::cout << "Per favore scrivi un numero intero: ";
 +  std::cin >> mioNumero;
 +  ​
 +  std::cout << "il triplo di " << mioNumero
 +            << " vale " << triplicare(mioNumero) "​.\n";​
 +  return 0;
 +}
 +</​file>​
 +
 +Il nuovo alias davanti alla funzione evita di creare una nuova variabile temporanea che sarebbe necessaria anche per restituire il valore con //​return//​. ​
 +Il nuovo //const// davanti alla funzione impedisce modifiche indesiderate a tale oggetto locale.
 +
 +I const reference sono anche l'​unico modo con cui si possono utilizzare gli oggetti temporanei inaccessibili (come le espressioni costanti o gli oggetti temporanei restituiti da una funzione)
 +
 +vedere //Thinking in C++, capitolo 11: References & the Copy-Constructor pag.477//
 +
 +====== Funzioni costanti ======
 +
 +Le funzioni costanti sono importanti perché sono un buono strumento di correzione degli errori.
 +Basta aggiungere un modificatore //const// in fondo (alla fine) della firma della funzione.
 +Questo evita modifiche accidentali ai dati degli oggetti
 +
 +Basta scrivere //const// __in fondo__ al nome della funzione per costringere il compilatore a fare un controllo che quella funzione non esegua alcuna istruzione di modifica su TUTTI i membri dato di quell'​oggetto. Per questo motivo dovrebbe essere usato su tutte le funzioni di tipo ispettore (vedi [[appunti3s:​programmi_procedurali#​classificazione|classificazione delle funzioni]])
 +
 +Le funzioni di questo tipo sono anche le uniche che possono avere come argomenti interi oggetti costanti come:
 +  * const Classe unOggetto
 +  * const& Classe unOggetto
 +  * const Classe* unOggetto
  
  • appunti3s/cenni_ai_references.txt
  • Last modified: 2018/04/25 07:55
  • (external edit)