Passaggio di parametri per valore o per riferimento

In C++ ci sono due modi per il passaggio dei parametri alle funzioni: passaggio di parametri per valore o per riferimento.

Passaggio di parametri per valore

Nel passaggio per valore, i valori delle variabili vengono copiati e passati alla funzione, invece di passare direttamente l’indirizzo di memoria delle variabili stesse. Ecco cosa succede quando si utilizza il passaggio per valore:

  1. Creazione di copie dei dati: Quando una funzione viene chiamata e i parametri vengono passati per valore, vengono create copie locali dei valori delle variabili passate. Queste copie vengono utilizzate all’interno della funzione, mentre i valori originali delle variabili rimangono invariati.
  2. Modifiche locali: Le modifiche apportate ai parametri all’interno della funzione non influiscono sui valori delle variabili originali nell’ambito della chiamata alla funzione. Poiché le modifiche vengono apportate alle copie locali dei parametri, i valori delle variabili originali rimangono invariati.
  3. Scopo locale: Le variabili definite all’interno della funzione sono visibili e accessibili solo all’interno di quella funzione. Le modifiche apportate ai parametri all’interno della funzione rimangono all’interno della funzione stessa e non influenzano le variabili originali all’esterno della funzione.

In sostanza, il passaggio per valore è utile quando si desidera che i valori delle variabili passate a una funzione siano protetti da modifiche accidentali o indesiderate all’interno della funzione stessa. Tuttavia, poiché vengono create copie dei dati, può essere meno efficiente in termini di memoria rispetto al passaggio per riferimento, specialmente per dati di grandi dimensioni.

Per capire bene il concetto facciamo da un esempio dove la funzione swap() accetta due parametri a e b passati per valore. Ciò significa che, quando la funzione swap() viene chiamata nel main(), vengono passate copie dei valori delle variabili x e y, anziché i loro indirizzi di memoria.

Ecco il codice completo:

#include <iostream>
using namespace std;

// Funzione per scambiare due interi
void swap(int a, int b) {
    int temp; // Variabile temporanea per lo scambio

    temp = a; // Salva il valore di a in temp
    a = b;    // Assegna il valore di b a a
    b = temp; // Assegna il valore salvato in temp a b
}

int main() {
    int x, y;
    
    // Input di due numeri da parte dell'utente
    cout << "Inserisci il numero x: ";
    cin >> x;
    cout << "Inserisci il numero y: ";
    cin >> y;

    // Chiamata alla funzione swap() per scambiare i valori di x e y
    swap(x, y);

    // Output dei valori di x e y dopo lo scambio
    cout << "Dopo lo scambio:" << endl;
    cout << "x: " << x << endl;
    cout << "y: " << y << endl;

    return 0;
}

In quest’esempio la funzione swap ha lo scopo di scambiare il valore di a con quello di b e viceversa, utilizzando una variabile temporanea.

Nel main poi inserisco due valori e richiamo la funzione swap su di essi.

Stampo i valori in output ma non sono cambiati!

Perché? Non sono cambiati perché lo scambio è avvenuto all’interno della funzione swap ma non si può riflettere al di fuori di essa. La funzione swap infatti non restituisce un valore ma fa un’operazione di scambio che avviene all’interno della funzione stessa.

Diverso infatti quando scriviamo:

int somma (int a, int b)
{
   int s;
   s = a + b;
   return s;
}

Infatti in questo caso si ha un passaggio di parametri per valore ma la funzione mi ritorna la somma. E quindi quando poi vado a richiamare la funzione nel main mi restituirà effettivamente la somma.

Il discorso nell’esempio dello swap è ben diverso dunque.

Le operazioni di scambio vengono eseguite utilizzando le variabili locali a e b. Tuttavia, queste operazioni non influenzano le variabili originali x e y all’esterno della funzione, poiché si tratta di copie locali:

swap(x, y);

Dopo la chiamata alla funzione swap(), i valori di x e y nel main() rimangono invariati, poiché le modifiche effettuate all’interno della funzione swap() sono state apportate solo alle copie locali dei parametri.

In sostanza, poiché i parametri vengono passati per valore, le modifiche ai valori all’interno della funzione swap() non influenzano i valori delle variabili originali all’esterno della funzione stessa. Pertanto, l’output del programma mostrerà ancora i valori originali di x e y dopo la chiamata alla funzione swap().


Passaggio di parametri per riferimento

Un’altra modalità di passaggio di parametri è quello per riferimento.

Il passaggio per riferimento è un concetto fondamentale in programmazione, particolarmente importante in linguaggi come C++ che supportano la manipolazione diretta della memoria. In breve, il passaggio per riferimento consente a una funzione di accedere e modificare direttamente i valori di una variabile definita all’esterno della funzione stessa, senza creare una copia separata dei dati.

Ecco alcuni punti chiave sul passaggio per riferimento:

  1. Passaggio per riferimento vs. Passaggio per valore: In C++, i parametri di una funzione possono essere passati per valore o per riferimento. Nel passaggio per valore, viene creata una copia separata dei dati passati alla funzione, quindi eventuali modifiche ai parametri all’interno della funzione non influenzeranno i valori delle variabili originali. Nel passaggio per riferimento, invece, viene passato un riferimento alla variabile originale, consentendo alla funzione di operare direttamente sui dati originali.
  2. Utilizzo dell’operatore “&”: Per definire un parametro di una funzione come passaggio per riferimento, si utilizza l’operatore “&” prima del nome del parametro. Ad esempio, void swap(int &a, int &b) definisce due parametri a e b come passaggi per riferimento.
  3. Modifica diretta dei valori: Quando si passa una variabile per riferimento a una funzione e si opera su quella variabile all’interno della funzione, qualsiasi modifica apportata ai valori del parametro influenzerà direttamente i valori delle variabili originali definite nell’ambito della chiamata alla funzione.
  4. Miglior leggibilità e performance: Il passaggio per riferimento è spesso preferito rispetto al passaggio per valore quando si desidera modificare direttamente i valori delle variabili originali all’interno di una funzione. È anche più efficiente in termini di memoria, poiché non richiede la creazione di copie dei dati.

Creiamo dunque una funzione swap() che accetta due parametri a e b passati per riferimento. Questi parametri vengono utilizzati per scambiare i valori delle variabili che rappresentano due numeri interi x e y. Quando la funzione swap() viene poi chiamata nel main(), i valori di x e y vengono passati alla funzione per riferimento.

All’interno della funzione swap(), i valori di a e b sono effettivamente alias per le variabili x e y nella memoria. Quindi, le operazioni di assegnazione a = b; e b = temp; modificano direttamente i valori di x e y rispettivamente.

Dopo la chiamata alla funzione swap(), i valori di x e y nel main() sono stati scambiati con successo grazie all’utilizzo del passaggio per riferimento. Di conseguenza, l’output mostrerà i nuovi valori delle variabili x e y dopo lo scambio.

Ecco dunque il codice di esempio:

    #include <iostream>
    using namespace std;
    
    // Funzione per scambiare i valori di due interi utilizzando il passaggio per riferimento
    void swap(int &a, int &b) {
        int temp = a; // Salva il valore di a in una variabile temporanea
        a = b;        // Assegna il valore di b a a
        b = temp;     // Assegna il valore salvato in temp a b
    }
    
    int main() {
        int x, y;
        
        // Input di due numeri da parte dell'utente
        cout << "Inserisci il numero x: ";
        cin >> x;
        cout << "Inserisci il numero y: ";
        cin >> y;
    
        // Chiamata alla funzione swap() passando le variabili per riferimento
        swap(x, y);
    
        // Output dei valori di x e y dopo lo scambio
        cout << "Dopo lo scambio:" << endl;
        cout << "x vale: " << x << endl;
        cout << "y vale: " << y << endl;
    
        return 0;
    }
    

    Questi sono solo dei semplici esempi per spiegare il passaggio di parametri per valore o per riferimento.

    Alcuni link utili:

    Ciclo while in C++

    Ciclo do while

    Iterazioni con il ciclo for in C++

    Operatori logici in C++

    Esercizi con switch case in C++

    Switch case in C++

    If else in C++

    Casting in C++

    Variabili in C++

    Tutorial C++

    Successione di Fibonacci in C++


    Lascia un commento

    Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *