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

Întoarcerea pointerilor și referințelor

Întoarcerea unui pointer

La întoarcerea unui pointer dintr-o funcție, acesta trebuie să conțină fie valoarea nullptr, fie o adresă care este încă valabilă. Prin urmare, nu ar trebui returnată din funcție adresa unei variabile locale automate, deoarece aceasta este ștearsă după finalizarea funcției. De exemplu, să analizăm următorul exemplu incorect de funcție care returnează numărul mai mare dintre două:

// exemplu incorect de întoarcere a unei valori
int* max(int a, int b)
{
    if (a > b)
        return &a;
    else
        return &b;
}

Parametrii funcției sunt analogi variabilelor - la apelul funcției li se alocă memorie în stivă. În acest caz, se returnează adresa unei secțiuni de memorie corespunzătoare parametrului (return &a sau return &b). Dar după întoarcerea adresei, funcția își încheie execuția, secțiunile de memorie corespunzătoare sunt eliberate, parametrii sunt eliminați, astfel încât adresa returnată va fi invalidă. Deși compilatorul poate chiar să compileze această funcție, limitându-se la avertismente, o astfel de funcție nu va funcționa corect.

Totuși, asta nu înseamnă că, în principiu, nu putem returna un pointer dintr-o funcție. De exemplu, să luăm următoarea situație:

#include <iostream>
 
int* max(int*, int*);
 
int main()
{
    int n{5};
    int m{4};
    int* ptr = max(&n, &m);
    std::cout << "max: " << *ptr << std::endl; // max: 5
}
// exemplu corect de întoarcere a unei valori
int* max(int *a, int *b)
{
    if (*a > *b)    // dereferențiem pointerii
        return a;
    else
        return b;
}

Aici este o funcție similară care calculează valoarea maximă dintre două numere, doar că se transmit adresele variabilelor, nu valorile lor. De aceea, adresa returnată va rămâne valabilă.

În același timp, nu este obligatoriu să atribuim rezultatul unei variabile sau constante, putem accesa direct rezultatul funcției:

int main()
{
    int n{5};
    int m{4};
    std::cout << "max: " << *max(&n, &m) << std::endl; // max: 5
}

Întoarcerea unei referințe

O funcție poate returna și o referință. Totuși, ne putem confrunta cu aceleași probleme ca la întoarcerea pointerilor: nu ar trebui returnată o referință la un obiect local creat în funcție. Deoarece toate obiectele create în funcție sunt eliminate după încheierea acesteia, iar memoria lor este eliberată, referința returnată va indica spre un obiect inexistent, ca în următorul caz:

// exemplu incorect de întoarcere a unei referințe
int& max(int a, int b)
{
    if (a > b) 
        return a;
    else
        return b;
}

Aici funcția returnează o referință la valoarea maximă - unul dintre parametrii transmiși. Dar deoarece memoria alocată pentru parametrii transmiși prin valoare este eliberată după executarea funcției, referința returnată va indica un obiect inexistent.

Pentru a ieși din această situație, putem transmite valorile prin referință:

#include <iostream>
 
int& max(int&, int&);
 
int main()
{
    int n{5};
    int m{4};
    int result = max(n, m);
    std::cout << "max: " << result << std::endl; // max: 5
}
// exemplu corect de întoarcere a unei referințe
int& max(int& a, int& b)
{
    if (a > b) 
        return a;
    else
        return b;
}

Este de remarcat că, dacă parametrii sunt referințe constante, pentru a returna una dintre aceste referințe, funcția trebuie să returneze o referință constantă:

#include <iostream>
 
const int& max(const int&, const int&);
 
int main()
{
    int n{5};
    int m{4};
    int result = max(n, m);
    std::cout << "max: " << result << std::endl; // max: 5
}
// exemplu corect de întoarcere a unei referințe
const int& max(const int& a, const int& b)
{
    if (a > b) 
        return a;
    else
        return b;
}