Parameters: by value and by reference
Picture handing a colleague a document to edit. You can hand over a photocopy: the colleague scribbles all over it, and your original stays clean. Or you can hand over the original itself, and then every edit ends up on your copy. A C++ function also gets its argument in one of these two ways, and the call does not show which.
The inc_copy function increases its parameter by one, but the variable passed to it stays the same:
#include <iostream>
void inc_copy(int x) {
++x;
std::cout << x << '\n'; // 2
}
int main() {
int n = 1;
inc_copy(n);
std::cout << n << '\n'; // 1
}Inside the function, x is already 2, while n in main is still 1.
A copy of the argument
Let's walk through the call inc_copy(n) step by step:
- A new variable
xis created, and the value of the argumentn, that is1, is copied into it. ++xincreases the copy to2, and the function prints2.- The function ends, and
xdisappears together with every change made to it. mainprintsn, andnis still1.
This is pass by value: the function works with a photocopy, not with n itself. The analogy limps in one place: you cannot take the copy home, since it lives only until the function ends.
A changed copy can be returned with return: the caller gets the new value, and the original variable stays as it was.
Reference parameters
To let a function change the caller's variable, the parameter is declared as a reference: an & goes after the type. A reference is another name for an existing variable, not a copy of it. It works like a nickname: "Sasha" and "Alexander" are one and the same person.
#include <iostream>
void inc_ref(int& x) {
++x;
}
int main() {
int n = 1;
inc_ref(n);
std::cout << n << '\n'; // 2
}Inside inc_ref, the name x denotes n itself, so ++x increases n. The call creates no new variable: for the duration of the call, one variable has two names.
Step through both calls and watch n in the main frame: after inc_copy it is unchanged, after inc_ref it is not.
1–2#include <iostream>3void inc_copy(int x) {4 ++x;5 std::cout << x << "\n";6}7 8void inc_ref(int& x) {9 ++x;10}11 12int main() {13 int n = 1;14 inc_copy(n);15 std::cout << n << "\n";16 inc_ref(n);17 std::cout << n << "\n";18}
main gets n with the value 1
The call looks the same as inc_copy(n): only the function's declaration tells you that the argument will change. So when you read someone else's code, look for the & in the parameter list.
"How does pass by value differ from pass by reference?" is a question interviewers like to ask. The short answer: by value the function gets a copy, by reference it gets the variable itself.
Common mistake
A number is passed to a function that takes a reference:
void inc_ref(int& x) {
++x;
}
int main() {
inc_ref(5); // ✗
}error: no matching function for call to 'inc_ref'This is a compiler error. A reference must become another name for some variable, and the number 5 has no variable of its own: there is nothing to increase. Pass a variable instead, for example inc_ref(n).
Key points
- By value, the function gets a copy of the argument; its changes vanish with the copy.
- A reference parameter
int& xis another name for the caller's variable; changes are visible outside. - The calls
inc_copy(n)andinc_ref(n)look the same: only the&in the declaration shows the difference. - Only a variable can be passed to an
int¶meter, not a number such as5.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.