Skip to content
Theory · Functions · lesson 2 of 11

Parameters: by value and by reference

The inc_copy function increases its parameter by one, but the variable passed to it stays the same:

C++
#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.

C++
#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:

C++
const int& sum(int a, int b) {
    int result = a + b;
    return result;  // ✗
}
TEXT
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).