Parametri prin valoare — funcția lucrează pe o copie

Bază~14 min9 pași

De ce contează?

Îi dai unui prieten o fotocopie a temei, nu caietul tău. El poate scrie pe copie, o poate mototoli — caietul tău rămâne intact. Transmiterea prin valoare e exact asta: funcția primește o fotocopie a valorii și nu poate strica originalul.

Ce înseamnă transmiterea prin valoare?

Când un parametru e transmis prin valoare, funcția primește o copie a argumentului. Orice modificare făcută pe parametru afectează doar copia, nu variabila originală din apel.

Aceasta e comportarea implicită în C++ pentru tipuri simple (int, double, char, ...): dacă scrii int x în antet, e prin valoare.

Observația-cheie

La apel se creează o copie nouă a valorii și se pune în parametru. Când funcția se termină, copia se distruge. Originalul nici nu „știe" că s-a întâmplat ceva.

Exemplul clasic

#include <iostream>
using namespace std;

void creste(int x) {
    x++;                 // modifica doar copia
    cout << "in functie: " << x << "\n";
}

int main() {
    int a = 5;
    creste(a);           // in functie: 6
    cout << "in main: " << a << "\n";  // in main: 5
    return 0;
}

În funcție, x ajunge 6. Dar în main, a e tot 5 — modificarea a atins doar copia.

Privit ca diagramă, la apel argumentul a se copiază în parametrul x:

5
5
a
copie-x
La apel, x primește o copie a lui a. Sunt două cutii separate în memorie.

După x++, doar a doua cutie se schimbă:

5
6
a
copie-x
x++ schimbă doar copia. a rămâne 5; la finalul funcției copia dispare.

Urmărire pas cu pas

main: a = 5
main: apel creste(a)  -> se copiaza 5 in x
  creste: x = 5
  creste: x++  -> x = 6   (a NU se atinge)
  creste: afiseaza 6
  creste: se termina -> x se distruge
main: afiseaza a = 5

De ce e util

Transmiterea prin valoare e sigură: garantezi că funcția nu strică datele apelantului. E alegerea potrivită când funcția doar citește valoarea ca să calculeze ceva — maxim(a, b), patrat(n), esteParfect(x). Originalul rămâne protejat.

int patrat(int n) {
    return n * n;   // foloseste n, nu-l modifica in afara
}

Și atunci cum modific originalul?

Dacă chiar vrei ca funcția să schimbe variabila din apel (de exemplu un swap), prin valoare nu merge — modifici doar copia. Pentru asta există transmiterea prin referință, subiectul lecției următoare.

Greșeli frecvente

Capcane la transmiterea prin valoare:

  • Te aștepți ca funcția să modifice argumentul: creste(a) cu parametru prin valoare nu schimbă a. Ai nevoie de referință.
  • Copiezi obiecte mari fără motiv: pentru un string lung sau o structură mare, copierea costă timp. Acolo se folosește referința (eventual constantă), nu valoarea.
  • Crezi că return-ul nu mai e necesar: dacă lucrezi pe copie, singurul mod de a scoate rezultatul afară e prin return.
  • Confuzi parametrul cu argumentul: au valori egale la pornire, dar sunt cutii diferite în memorie.

Recapitulare

  • Prin valoare, parametrul e o copie a argumentului; modificările nu ating originalul.
  • E comportarea implicită pentru tipurile simple și e sigură — protejează datele apelantului.
  • Pentru a modifica efectiv variabila din apel, ai nevoie de transmitere prin referință.

Întrebarea 1 / 3

Ce primește un parametru transmis prin valoare?