Nell'esempio precedente, gli argomenti sono stati passati alla funzione per valore. Quando il passaggio dei parametri avviene per valore, alla funzione viene in effetti passata solo una copia dell'argomento. Grazie a questo meccanismo il valore della variabile nel programma chiamante non viene modificato.
Il passaggio di parametri per valore è un modo molto comune per passare informazioni a una funzione ed è anche il modo normalmente utilizzato in C++.
In passaggio di parametri per riferimento (o reference), alla funzione viene passato l'indirizzo e non il valore dell'argomento. Questo approccio richiede meno memoria rispetto alla chiamata per valore, e soprattutto consente di modificare il valore delle variabili che sono ad un livello di visibilità (scope) esterno alla funzione o al metodo.
Passaggio di parametri per indirizzo
Prima di affrontare il passaggio per riferimento, ci aiuterà esaminare un altro modo per passare gli argomenti ad una funzione: quello del passaggio per indirizzo, molto simile a quello per riferimento, in cui è necessario passare alla funzione degli argomenti di tipo puntatore.
Un vantaggio in più del passaggio per indirizzo rispetto a quello per valore è che la variabile può restituire più di un valore. Facciamo subito un esempio in cui riproponiamo la funzione che calcola la moltiplicazione tra due numeri ma con i parametri passati per indirizzo.
#include <iostream.h>
using namespace std;
// Definizione del prototipo
int moltiplica(int* x, int* y);
main()
{
int a = 5;
int b = 6;
int risultato;
risultato = moltiplica(&a, &b);
cout << Il risultato della moltiplicazione è: << risultato <<endl;
return (0);
}
// Dichiarazione della funzione
int moltiplica(int* x, int* y)
{
int ris;
// effettua la moltiplicazione tra i valori che si
// trovano leggendo il contenuto della memoria
// agli indirizzi x e y, tramite il prefisso '*'
// (da non confondere con l'operatore di moltiplicazione)
ris = *x * *y;
// Valore restituito dalla funzione.
return ris;
}
Passaggio di parametri per riferimento
Il tipo reference è un puntatore ad un indirizzo di memoria, ma non richiede l'uso di un operatore di indirizzamento (il prefisso asterisco '*' per intenderci).
La sintassi che stiamo per osservare semplifica l'uso delle variabili puntatore nelle chiamate alle funzioni. Si capisce immediatamente confrontando il codice dell'esempio precedente con quello che segue:
#include <iostream.h>
using namespace std;
// Definizione del prototipo
int moltiplica(int &x, int &y);
main()
{
int a = 5;
int b = 6;
int risultato;
risultato = moltiplica(a, b);
cout << Il risultato della moltiplicazione è: << risultato <<endl;
return (0);
}
// Dichiarazione della funzione
int moltiplica(int &x, int &y)
{
int ris;
// moltiplica ciò che trova presso gli indirizzi di memoria di x e y
// ma non c'è bisogno di esplicitarlo
ris = x * y;
// Valore restituito dalla funzione
return ris;
}
Void, funzioni ...senza ritorno
È utile ricordare che in C++ possono tranquillamente esistere funzioni che non prendono nessun argomento e/o che non restituiscono alcun valore. A qualcuno queste ultime ricorderanno le "procedure" del Pascal: ovvero subroutine di codice che non restituivano alcun valore. In C++, le definiamo semplicemente stabilendo che tipo restituito dalla funzione sia void. Esempio:
void stampaCiao()
{
cout <<"Ciao" <<endl;
}