Parameters: by value and by reference
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
The call inc_copy(n) creates a new variable x and copies the value of the argument n into it. This is pass by value: the function works with a copy, not with n itself. The copy lives until the function ends and disappears together with every change made to it.
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.
#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 looks the same as inc_copy(n): only the function's declaration tells you that the argument will change. The argument here must be a variable: the call inc_ref(5) has nothing to increase, so it does not compile.
Const references
Copying an int or a double is cheap, so such parameters are passed by value. But objects of some types hold thousands of values, and copying one on every call is expensive. A parameter of such a type is declared as a const reference, const T&, where T is the parameter's type. There is no copy, as with a plain reference, but the function cannot change the argument: the compiler rejects any attempt.
A const reference also accepts a literal such as 5, since the function will not change it anyway.
Common mistake
A function returns a reference to its own local variable:
const int& sum(int a, int b) {
int result = a + b;
return result; // ✗
}warning: reference to stack memory associated with local variable 'result' returned [-Wreturn-stack-address]The compiler only warns, but result is destroyed when the function returns, and the reference is left without a variable. Such a reference is called dangling, and reading through it is undefined behavior. Return the result by value: int sum(int a, int b).