Skip to content

Pass by Value or Reference

There are actually two ways that values can be passed to parameters: pass by value and pass by reference.

So far we have been using pass by value for all of our parameters. With pass by value, the parameter receives a copy of the value passed in the argument. In this case, any expression is evaluated first, and the value copied across.

With pass by reference you have to pass a variable, a location to store a value. Pass by reference allows you to pass across a location where a value can be stored, and from which a value can be read.

Shows you can pass a variable to a by reference parameter

By Reference - Why, When, and How

You can use pass by reference for a couple of purposes:

  • To allow the called function or procedure to update the value passed.
  • To improve performance when passing large data structures.

Updating passed values

Breaking up our code into smaller functions and procedures is really important to help us build and manage the code in larger programs. So far, parameters have allowed us to pass values into these functions/procedures but we in some cases we also want that code to update variables that we pass it.

With pass by reference, you can create functions and procedures that can update the variables passed to it. In most cases these will be procedures, where the action performed has a side effect on the parameter passed in. For example, in our fly game we could create a handle_input procedure that is passed the spider to update. In handle_input, the code can read and change the data passed to it, allowing it to update the position of the spider in response to user input.

Improve performance

When we started using parameters we were passing simple data values like individual numbers, but with structs these parameters can now be passed potentially large volumes of data. Copying this data in by value takes time, as the computer has to duplicate all the information in the struct to copy it by value.

References are achieved by passing the address of the variable passed to it. This is always the same size, and can be passed efficiently to the parameter. For example, in draw_game we need to pass all the data associated with the game. You can pass this by reference to save time duplicating the game.

In these instances you can indicate that you want to pass these as constant references, ensuring that the caller does not change the value passed to it.

In C++

Example

#include <splashkit.h>
using std::to_string;
void double_it(int &data)
{
write_line("Data passed in was " + to_string(data) + ", about to double it...");
data = data * 2;
write_line("In double_it data is now " + to_string(data));
}
int main()
{
int val = 3;
int other = 1;
write_line("In main val is " + to_string(val));
double_it(val);
write_line("Back in main val is now " + to_string(val));
double_it(other);
}

This will output the following when run. Notice that the value in the val variable in main is updated, as will the value in the other variable. Also notice that there is no special syntax needed in the function call, though you have to pass it a variable. Trying to pass this an expression like other + 1 would fail with a compiler error, as a parameter passed by reference requires a variable not just a value passed to it.

In main val is 3
Data passed in was 3, about to double it...
In double_it data is now 6
Backin main val is now 6
Data passed in was 1, about to double it...
In double_it data is now 2

By Reference Up Close

The program begins at main(), with lines 3 and 4 declaring and initializing two int variables 'val' and 'other' on the stack. Notice that when the variables are created on the stack, they have a memory address associated with them.
Line 5 prints the value of 'val' to the terminal
Line 6 then contains a call to the function <strong>double_it</strong>, which is passed the variable 'val' as a parameter
double_it is called and receives the parameter 'val' as 'call by reference'. This means that instead of storing a copy of the value of 'val', it stores the 'address' of val'. Any operations using data in 'double_it()', will be therefore operating on val in main().
Line 12 prints the (dereferenced) value of <strong>data</strong> (i.e. the value of <strong>val</strong>) to the terminal
Line 13 doubles the value of <strong>data (val)</strong>, and stores it back in the same variable
Line 14 writes the new value of <strong>data (val)</strong> to the terminal
The call to double_it ends, and control returns to <strong>main</strong>. The data variable is removed from the stack
The new value of val is written to the terminal. You can see that the doubling operation performed by the call to double_it() has changed the value of val in main()
Line 8 contains another call to double_it, this time passing the variable other as a parameter
Once again, the local variable data in the double_it function stores a pointer to the variable 'other' in main
Line 12 writes the (dereferenced) value of data to the terminal
Line 13 doubles the (dereferenced) value of data and stores it back in data
Line 14 writes the new (dereferenced) value of data< to the terminal
The double_it function returns, and the data variable is wiped from the stack
The main() function ends, and it's variables are also wiped from the stack, ending the program