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

Indicatori în parametrii funcției

Parametrii funcției în C++ pot fi pointeri. Pointerii sunt transmiși funcției prin valoare, adică funcția primește o copie a pointerului. În același timp, copia pointerului va avea ca valoare aceeași adresă ca și pointerul original. Prin urmare, folosind pointeri ca parametri, putem accesa valoarea argumentului și o putem modifica. De exemplu, să avem o funcție simplă care crește un număr cu unu:

#include <iostream>
 
void increment(int);
 
int main()
{
    int n {10};
    increment(n);
    std::cout << "main function: " << n << std::endl;
}
void increment(int x)
{
    x++;
    std::cout << "increment function: " << x << std::endl;
}

Aici variabila n este transmisă ca argument pentru parametrul x. Transmiterea are loc prin valoare, astfel încât orice modificare a parametrului x în funcția increment nu va afecta valoarea variabilei n. Ceea ce putem vedea rulând programul:

increment function: 11
main function: 10

Acum modificăm funcția increment, folosind ca parametru un pointer:

#include <iostream>
 
void increment(int*);
 
int main()
{
    int n {10};
    increment(&n);
    std::cout << "main function: " << n << std::endl;
}
void increment(int *x)
{
    (*x)++;
    std::cout << "increment function: " << *x << std::endl;
}

Pentru a modifica valoarea parametrului se folosește operatorul de dereferențiere urmat de incrementare: (*x)++. Aceasta modifică valoarea aflată la adresa stocată în pointerul x.

Deoarece acum funcția primește un pointer ca parametru, la apel trebuie să transmitem adresa variabilei: increment(&n);. În cele din urmă, modificarea parametrului x va afecta și variabila n, deoarece ambele păstrează aceeași adresă de memorie:

increment function: 11
main function: 11

În același timp, deoarece argumentul este transmis funcției prin valoare, adică funcția primește o copie a adresei, dacă în interiorul funcției se modifică adresa pointerului, aceasta nu va afecta pointerul extern transmis ca argument:

#include <iostream>
 
void increment(int*);
 
int main()
{
    int n {10};
    int *ptr {&n};
    increment(ptr);
    std::cout << "main function: " << *ptr << std::endl;
}
void increment(int *x)
{
    int z {6};
    x = &z;
    std::cout << "increment function: " << *x << std::endl;
}

În funcția increment este transmis pointerul ptr, care stochează adresa variabilei n. La apel, funcția increment primește o copie a acestui pointer prin parametrul x. În funcție, adresa pointerului x este schimbată cu adresa variabilei z. Dar aceasta nu va afecta pointerul ptr, deoarece reprezintă o altă copie. Ca rezultat, după modificarea adresei, pointerii x și ptr vor conține adrese diferite.

Rezultatul rulării programului:

increment function: 6
main function: 10

Parametri-pointer constanți

Parametrii care reprezintă pointeri pot fi constanți:

#include <iostream>
  
void print(const int*);
 
int main()
{
    int n {10};
    print(&n);
}
void print(const int *x)
{
    std::cout << *x << std::endl;
}

Prin intermediul unui parametru constant nu putem modifica valoarea. Astfel de parametri reprezintă de fapt pointeri către constante. Prin urmare, parametrii constanți sunt utili atunci când trebuie să transmitem funcției adresa unei constante – în acest caz parametrul trebuie să fie neapărat constant:

#include <iostream>
  
void print(const int*);
 
int main()
{
    const int n {10};
    print(&n);
}
void print(const int *x)
{
    std::cout << *x << std::endl;
}

Totuși, faptul că parametrul este constant nu înseamnă că nu putem modifica adresa stocată în pointer, de exemplu așa:

void print(const int *x)
{
    int z{2};
    x = &z;
    std::cout << *x << std::endl;
}

Pentru a garanta că nu se va modifica nici valoarea de la adresa pointerului, nici adresa în sine, pointerul trebuie definit ca fiind constant:

#include <iostream>
  
void print(const int*);
 
int main()
{
    const int n {10};
    print(&n);
}
void print(const int* const x)
{
    int z{2};
    //x = &z;
    std::cout << "z = " << z << std::endl;
    std::cout << "*x = " << *x << std::endl;
}

Parametri prin referință sau parametri-pointer

Parametrii transmiși prin referință și parametrii-pointer sunt similari în sensul că ambele tipuri permit modificarea valorilor variabilelor transmise. Singura diferență esențială este că un pointer poate avea valoarea nullptr, în timp ce o referință trebuie să fie întotdeauna legată de ceva. Prin urmare, dacă este nevoie ca un parametru să nu aibă nicio valoare, se pot folosi pointeri. Singurul lucru este că, în acest caz, trebuie verificat dacă pointerul este nullptr înainte de utilizare.