call by value (tsz. call by values)
A call by value esetén a függvény paraméterei másolatot kapnak az átadott értékből. Vagyis a függvény belsejében végzett módosítások nem hatnak vissza az eredeti változóra a függvényen kívül.
Ez a paraméterátadási mechanizmus sok programozási nyelvben az alapértelmezett (pl. C, Java primitív típusoknál, C++, Python speciális módon). Nézzük meg részletesen.
Amikor egy függvényt hívsz meg, és paraméterként egy értéket adsz át, a következő történik:
#include <stdio.h>
void modify(int x) {
x = x + 10;
printf("A függvényben x: %d\n", x);
}
int main() {
int a = 5;
printf("Hívás előtt a: %d\n", a);
modify(a);
printf("Hívás után a: %d\n", a);
return 0;
}
Kimenet:
Hívás előtt a: 5 A függvényben x: 15 Hívás után a: 5
Látható, hogy bár a függvényben x
értékét megnöveltük, az a
változó a main
függvényben nem változott. Miért? Mert a függvény csak a
másolatán dolgozott (x
).
Amikor meghívod a modify(a)
függvényt, a main
-ben lévő a
értéke (5) lemásolódik az x
paraméterbe.
Az x
változó egy teljesen különálló példány, nem ugyanaz a memóriahely, mint a
.
A x = x + 10;
sor csak az x
másolatát módosítja. a
továbbra is 5 marad.
Amikor a függvény lefutott, az x
változó megszűnik (stack-ről lekerül), és az a
változó a main
-ben változatlan marad.
+---------+ +---------+ | a (5) | --> | x (5) | +---------+ +---------+ Függvény belül: x = x + 10 -> x = 15 Függvény vége után: +---------+ | a (5) | (változatlan) +---------+
Hogy lássuk a különbséget, nézzünk call by reference példát C++-ban:
#include <iostream>
using namespace std;
void modify(int &x) { // referencia
x = x + 10;
cout << "A függvényben x: " << x << endl;
}
int main() {
int a = 5;
cout << "Hívás előtt a: " << a << endl;
modify(a);
cout << "Hívás után a: " << a << endl;
return 0;
}
Kimenet:
Hívás előtt a: 5 A függvényben x: 15 Hívás után a: 15
Itt a függvény már az eredeti a
változót módosította, mert referenciát kapott, nem másolatot.
Nyelv | Alapértelmezett paraméterátadás |
---|---|
C | call by value |
C++ | call by value (de van referencia is) |
Java | primitívek: call by value, objektum referenciák: call by value of reference |
Python | call by object reference (speciális, de viselkedése call by value-hez hasonlít) |
JavaScript | call by value (de objektumok referenciái értékként másolódnak) |
Ez például Java és Python esetén így tűnhet. Miért?
Mert az objektum referenciáját adjuk át értékként (call by value of reference). A referencia ugyan másolat, de ugyanarra az objektumra mutat, így az objektum belső állapotát lehet módosítani. Viszont ha a referenciát teljesen újra próbálnád mutatni, az nem hat ki az eredeti változóra.