...
/References and Functions II (Pass by Reference)
References and Functions II (Pass by Reference)
Learn about reference variables and their applications in functions when parameters are received as references.
We'll cover the following...
In general, functions are used in programming to perform specific tasks and only return one value (if necessary) after processing any input arguments. It’s important to note that the memory allocated to a function will be released once the function has completed its task and returned any necessary value.
But what if we need more than one value from a particular function? Before discussing this, let’s first become familiar with the concept of reference variables.
Reference variable
To understand reference variables in C++, it’s important to understand the behavior of the ampersand (&) operator first. We can use this & operator to obtain the memory address of a variable.
Let’s look at an example.
#include <iostream>using namespace std;int main(){int a = 5;float c = 2.5;cout<< "Address of integer variable `a` is: " << &a<<'\n';cout<< "Address of float variable `c` is: " << &c<<'\n';return 0;}
In C++, a reference variable is a way to create an alias for an existing variable. The syntax for creating a reference variable involves using the & operator followed by the name of the variable we want to reference.
For example, consider a variable named a of the type int. To create a reference to a, we can use the following syntax:
int &aRef = a;
Here, aRef is a reference variable that refers to a. Note that the & operator is used to specify that aRef is a reference variable rather than a regular variable. The animation below can help illustrate how a reference variable acts as a new identifier for the same memory location.
It’s important to note that reference variables share the same memory address as the original variable. This means that any modifications made to the reference variable will also impact the original variable, and vice versa.
To understand this, consider the following code:
#include <iostream>using namespace std;int main(){int a = 5;int &aRef = a;cout << &a << " --- "<< &aRef <<'\n';cout << "Before incrementing\n";cout <<"Value of a : "<< a << " --- Value of aRef "<< aRef<<'\n';aRef++;cout <<"Value of a : " <<a << " --- Value of aRef "<< aRef<<'\n';return 0;}
Next, let’s look at an example in which we need to return two values.
Swapping values
We’re given two variables—alpha and beta—and we want to swap their values. For that, we shouldn’t do the following:
#include <iostream>using namespace std;int main(){int alpha = 5, beta = 4;alpha = beta; // alpha will become 4 and beta will be 4 too, and previous value of alpha is lostbeta = alpha; // This will be a logical error now as it will assign beta = 4cout << "alpha: "<< alpha << endl<< "beta: "<< beta <<endl;return 0;}
Line 6: We declare two integer variables,
alphaandbeta, and initializes them with the values5and4, respectively.Line 7: We assign the value of
betatoalphausing the assignment operator=. After this line executes, bothalphaandbetahold the value4.Line 8: We assign the value of
alphatobetausing the assignment operator=. After this line executes, bothalphaandbetahold the value4.
As a result, the values of alpha and beta have effectively been swapped, but not in the way that we intended. This is because the second assignment overwrites the value of beta with the incorrect value of alpha (which is now equal to the original value of beta).
Fixing the logical error
To fix this error, we need to create the temporary variable temp. The following illustration clearly describes the process of swapping.
Now that we understand the process, let’s write down the code for swapping.
#include <iostream>using namespace std;int main(){int alpha = 5;int beta = 4;cout<<"Before Swap"<<'\n';cout << "alpha : " <<alpha<<'\n';cout << "beta : " <<beta<<'\n';int temp = alpha;alpha = beta;beta = temp;cout<<"\nAfter Swap"<<'\n';cout << "alpha : " <<alpha<<'\n';cout << "beta : " <<beta<<'\n';return 0;}
Lines 6–7: We define the variables
alphaandbetawith valid states.Lines 11–13: We swap the values of variable
alphaandbetausing the temporary variabletemp.
Swapping values using functions
When we have to swap the values of two variables multiple times in our code, it can be tedious to repeat the same three lines of code because it can result in repetition. How can we avoid this?
One way to reduce this redundancy is to use a function to perform the swap operation.
Writing swap passed by value (a logical error)
The following code has a function called swap. We call this function erroneous because the parameters are passed by copy, which means that a new copy of each parameter is created in memory when the function is called. When the function returns, any changes made to these copies are lost, and the original variables remain unchanged.
Even if we create variables in the function with the same names as the calling position, the function will still operate on the copies rather than the original variables. This means that any changes made to the variables inside the function will not affect the variables in the calling position, rendering the function erroneous.
#include <iostream>using namespace std;void swap(int a, int b){int temp = a;a = b;b = temp;}int main(){int alpha = 5;int beta = 4;cout<<"Before Swap"<<'\n';cout << "alpha : " <<alpha<<'\n';cout << "beta : " <<beta<<'\n';swap(alpha, beta);cout<<"After Swap"<<'\n';cout << "alpha : " <<alpha<<'\n';cout << "beta : " <<beta<<'\n';return 0;}
Writing swap passed by reference (a correct solution)
To solve this problem, we can modify the function signature to include the & operator before the parameter names, which indicates that the parameters are passed by reference. Let’s take a look at the following code to see the correct implementation and how it executes.
#include <iostream>using namespace std;void swap(int &a, int &b){int temp = a;a = b;b = temp;}int main(){int alpha = 5;int beta = 4;cout << "Before Swap" << '\n';cout << "alpha : " << alpha <<'\n';cout << "beta : " << beta <<'\n';swap(alpha, beta);cout << "After Swap" <<'\n';cout << "alpha : " << alpha <<'\n';cout << "beta : " << beta <<'\n';return 0;}
This code defines a function called swap that takes two integer parameters by reference. The function swaps the values of the two parameters using a temporary variable.
Lines 11–12: We define two integer variables
alphaandbetawith initial values of5and4, respectively.Lines 13–15: We print the initial values of
alphaandbetato the console.Line 16: We call the
swapfunction withalphaandbetaas parameters. This will swap the values ofalphaandbetain the calling postion as well.Lines 17–19: After the swap, the new values of
alphaandbetaare printed to the console.
Let’s look at the following animation and see how the correct swap function works.
To gain more practice with passing by reference, we will now solve another nontrivial problem. In particular, we will explore how to simulate the return of multiple values from a function using pass-by-reference arguments. Although returning multiple values directly from a function isn’t possible, we can achieve this functionality by passing arguments by reference.
Exercise: Reduced fraction
You are given a fraction with two values: numerator and denominator. Your task is to reduce the fraction by implementing the functionality of the greatest common divisor (GCD) first and then calculate the reduced values of numerator and denominator.
Remember to compute the reduced fraction; all you have to do is compute the GCD of the numerator and denominator and divide both with the computed GCD.
For example,
Remember: You are not required to write the main() function. Just implement the two mentioned functions.
Note: You can't change the name of function and the number of parameters given in the prototypes of the
reduceFractionfunction.
#include <iostream>using namespace std;int GCD(int numerator,int denominator){// Write GCD code herereturn 1;}void reduceFraction(int &numerator,int &denominator){//Write your code here}