
Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: October 19, 2020
Variables play an important role in computer programming because they enable programmers to write flexible programs. A very important aspect that we need to keep in mind with variables is when we pass variables them as arguments to a function.
This tutorial explores what happens under the hood when the caller of a function passes arguments to the callee by value and by reference.
Call by value, also known as pass by value, is the most common way of passing arguments. When we pass a parameter by value, the caller and callee have two independent variables with the same value. Therefore, if the callee modifies its variable, the effect is not visible to the caller. Indeed, it has its own copy of the variable:
function callee(x passed by value):
x <- x + 1
function caller():
a <- 5
print a
callee(value of a)
print a
// Output when passing the parameter by value:
// 5
// 5
In the example above, the caller creates a variable and assigns the value
to it. At this point, when we print the value of
we clearly get
as a result.
The crucial step is when the caller calls the callee, passing the variable by value. The operating system creates a new independent variable
with the same value as
. When the callee modifies the variable
by simply adding
to it, the effects cannot be seen by the caller. Indeed, when the caller prints the
variable for the second time, we still get
as a result.
When we pass a variable by reference, the parameter inside the callee refers to the same object that the caller passed. As a consequence, any change operated by the callee on the object will be seen by the caller as well.
In other words, when a parameter is passed by reference, the caller and the callee use the same variable. If the function being called modifies this variable, the effect is visible to the caller’s variable:
function callee(x passed by reference):
x <- x + 1
function caller():
a <- 5
print a
callee(reference to a)
print a
// Output when passing the parameter by reference:
// 5
// 6
As in the previous example, the caller creates a variable and assigns the value
to it. When we print it, we get
as a result.
Then, the caller calls the callee, passing the variable by reference. The operating system creates an implicit reference
to variable
, rather than a brand new variable containing a copy of
‘s value. When the callee adds
to
, the effects can be seen by the caller. Indeed, the subsequent print statement returns
as a result.
Modern programming languages usually store data on the heap. Only “pointers” to it are ever held in variables and passed as parameters.
Passing such a pointer is still pass by value because a variable’s value is technically the pointer itself, not the pointed object. However, the final effect on the program can be the same as either pass by value or pass by reference:
By using call by reference, we have access to an additional channel of communication between the called function and the calling function. However, passing a variable by reference makes it more difficult to track the effects of a function call, and may introduce subtle bugs.
In this article, we’ve introduced the concepts of pass by value and pass by reference.