C++ - Pass by Reference

This post will go through the concept of pass by reference and its C++ implementation.

In C++, the arguments of a function can be passed by 3 methods: pass by value, pass by pointer and pass by reference
callee: A function that is called by another
caller: A function that calls another function

   

Pass by value

This is the method is usually used when we want to perform some calculations in a function using the value of the parameters. When we call a function that takes in a single parameter with pass by value, a copy of the caller function’s variable is passed into the callee function as an argument, where it will become a local variable. Note that this argument is just a copy callee function’s variable and they are two independent variables with the same value. This means that whatever changes that are made to the argument is not reflected to the original variable of the caller function.

void func(int a) {
    a = 10;
}

int main() {
    int a = 5;
    cout << a << endl; // Will output 5
    func(a);
    cout << a << endl; // Will still output 5
}

   

Pass by reference

Pass by reference is used when we want to directly modify the value of the arguments in the callee function. As its name suggest, pass by reference means passing the reference of an argument into the callee function In this case, we pass the memory address of a variable into the callee function instead of passing the actual content to it. This means that both of the the variable of the caller function and the variable that is passed to the callee function point to the same memory address. Therefore, any changes made to the local variable in the callee function will reflect to the original variable of the caller function. An alternative for pass by reference is pass by pointer.

   

Pass by pointer

Students who are learning C or C++ will probably find this more familiar. While this is a good practice for using pointers and has its own advantages, it is more complicated to write.

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int a = 5, b = 10;
    cout << a << ", " << b << endl; // Will output 5, 10
    swap(&a, &b);
    cout << a << ", " << b << endl; // Will output 10, 5
}

   

Pass by reference

As mentioned above, we can use pass by reference to do what we did using pass by pointer. In fact, the code will be simpler as we don’t need to explicitly pass in the reference of the variables and thus we don’t have to dereference them in the caller function.

void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int a = 5, b = 10;
    cout << a << ", " << b << endl; // Will output 5, 10
    swap(a, b);
    cout << a << ", " << b << endl; // Will output 10, 5
}

   

Both of the functions shown above will have the same functionality: they swap the value of the variables a and b of the caller function. It may appear that pass by pointer seems redundant and more difficult to code. However, it has its own advantages.

   

Comparison of Pass by reference and Pass by pointer

Pass by pointer Pass by reference
Creates a pointer that points to the memory address of the variable   Creates an alias (another name) for the variable
Need to dereference using * to get the value of the variable Can directly access and change the value of the variable
Can point to NULL Must be initialized during declaration
Can be reassigned to the memory address of another variable Can’t be reassigned to any other memory address
int main() {
    int a = 10;
    int b = 15;

    int& x = a; // Must be initialized during declaration
    x = b; // x becomes 15
    &x = b; // Error: Can't reassign x to another location
    &x = NULL; // Error: Can't reassign x to NULL

    int* y; // Can declare without initialization
    y = &a; // Can initialize after declaration
    y = &b; // Can reassign to another location
    y = NULL; // Can point to NULL
}

   

Summary

As we can see, there are some subtle differences between pass by pointer and pass by reference. If we just want a function to change the content of a variable we pass in, pass by reference is easier to write. However, we should also use pointers when we want to enjoy the extra benefits of using a pointer (reassigning to new memory locations).