MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Referințe

O referință (reference) reprezintă un mod de a manipula un obiect. Practic, o referință este un nume alternativ pentru un obiect. Pentru definirea unei referințe se folosește simbolul ampersand &:

int number {5};
int &refNumber {number};

În acest caz este definită referința refNumber, care face referire la obiectul number. Tipul referinței trebuie să fie același cu tipul obiectului la care face referire, în acest caz int.

Nu este permis să definim o referință fără a o inițializa:

int &refNumber; // eroare

De asemenea, nu putem atribui unei referințe o valoare literală, cum ar fi un număr:

int &refNumber = 10; // eroare

După ce am stabilit o referință, putem manipula prin ea obiectul la care face referire:

#include <iostream>
 
int main()
{
    int number {5};
    int &refNumber {number};
    std::cout << refNumber << std::endl; // 5
    refNumber = 20;
    std::cout << number << std::endl;   // 20
}

Modificările făcute prin referință afectează automat și obiectul la care aceasta face referire.

Putem defini nu doar referințe la variabile, ci și la constante. Însă, în acest caz, referința în sine trebuie să fie constantă:

const int number{5};
const int &refNumber{number};
std::cout << refNumber << std::endl; // 5
//refNumber = 20;       // nu putem modifica valoarea prin referință

Nu putem inițializa o referință neconstantă cu un obiect constant:

const int number {5};
int &refNumber {number}; // eroare

De asemenea, o referință constantă poate face referire și la o variabilă obișnuită, dar nu vom putea modifica valoarea prin acea referință:

int number {5};
const int &refNumber {number};
std::cout << refNumber << std::endl; // 5
 
//refNumber = 20;       // nu putem modifica valoarea prin referință constantă
     
// dar putem modifica direct variabila
number = 20;
std::cout << refNumber << std::endl;    // 20

În acest caz, deși nu putem modifica valoarea prin referința constantă, putem modifica obiectul direct, iar referința va reflecta noua valoare.

Referințe în ciclul for

În majoritatea cazurilor, referințele sunt utilizate în funcții, atunci când vrem să transmitem argumente prin referință (acest lucru va fi discutat în articolele următoare).

Totuși, există și alte scenarii de utilizare. De exemplu, în ciclul for de tip "for-each", nu putem modifica valorile elementelor parcurse. De exemplu:

#include <iostream>
 
int main()
{
    int numbers[] {1, 2, 3, 4, 5};
    // schimbăm valoarea în pătrat
    for (auto n : numbers)
    {
        n = n * n;
    }
    // afișăm rezultatul
    for (auto n : numbers)
    {
        std::cout << n << "\t";
    }
    std::cout << std::endl;
}

Aici sunt două cicluri. În primul ciclu, fiecare element este copiat în variabila n, care este apoi modificată. Dar modificarea nu afectează array-ul numbers. Elementele rămân neschimbate, așa cum vom vedea în al doilea ciclu:

1       2       3       4       5

Acum folosim referințe:

#include <iostream>
 
int main()
{
    int numbers[] {1, 2, 3, 4, 5};
    // acum n este o referință la elementul array-ului
    for (auto& n : numbers)
    {
        n = n * n;
    }
    // afișăm rezultatul
    for (auto n : numbers)
    {
        std::cout << n << "\t";
    }
    std::cout << std::endl;
}

Acum, în primul ciclu, n este o referință la elementul array-ului.

Folosirea unei referințe evită copierea valorii și permite modificarea directă a elementului:

1       4       9       16      25

Uneori, dimpotrivă, nu dorim să permitem modificarea elementelor. În acest caz, putem folosi o referință constantă:

#include <iostream>
 
int main()
{
    int numbers[] {1, 2, 3, 4, 5};
    // n este o referință constantă
    for (const auto& n : numbers)
    {
        std::cout << n << "\t";
    }
    std::cout << std::endl;
}

Deși nu putem modifica valoarea elementului, folosirea referinței optimizează parcurgerea array-ului, deoarece nu se face copiere în variabila n.