Pass by value and pass by reference (and reference variables)

Pass by value and Pass by Reference

We have seen as to how to pass values to a function through arguments. Actually there are two ways to pass values to a function through arguments. These two methods are explained below with examples.

Pass By Value:

Example:

void check (int x)
{

//body of function
}
int main ( )
{
int b = 10;
check (b);
}

In this function, ‘x’ is a parameter and ‘b’ (which is the value to be passed) is the argument. In this case the value of ‘b’ (the argument) is copied in ‘x’ (the parameter). Hence the parameter is actually a copy of the argument. The function will operate only on the copy and not on the original argument. This method is known as PASS BY VALUE. So far we have dealt only with pass by value (except when passing arrays to functions).

// Pass by value illustration

#include <iostream.h>

int square (int x)
{
return x*x;
}

int main ( )
{
int num = 10;
cout<<" Value of a is "<<num; // num will be 10
return 0;
}

You can see that the value of ‘num’ is unchanged. The function ‘square’ works only on the parameter (i.e. on x ). It does not work on the original variable that was passed (i.e it doesn't work on ‘num’). The diagram makes it quite clear as to what happens when we call square(num). The following initialization takes place:

int x = num;

and the function square( ) operates only on a copy of num.

Pass By Reference

In pass by reference method, the function will operate on the original variable itself. It doesn't work on a copy of the argument but works on the argument itself. Consider the same square function example:

// Illustration of pass by reference

#include <iostream.h>

void square (int *x)
{
*x = (*x) * (*x);
}

int main ( )
{
int num = 10;
square(&num);
cout<<" Value of num is "<<num; // Value of num is 100
return 0;
}

As you can see the result will be that the value of a is 100. The idea is simple: the argument passed is the address of the variable ‘num’. The parameter of ‘square’ function is a pointer pointing to type integer. The address of ‘num’ is assigned to this pointer. You can analyze it as follows: &num is passed to int *x, therefore it is the same as:

int *x = &num;

This means that ‘x’ is a pointer to an integer and has the address of the variable num.

Within the function we have:

*x = (*x) * (*x);

* when used before a pointer will give the value stored at that particular address. Hence we find the product of ‘num’ and store it in ‘num’ itself. i.e. the value of 100 is stored in the address of ‘num’ instead of 10 which was originally present there. The diagram below illustrates the difference between pass by value and pass by reference. Now when we dereference ‘x’ we are actually manipulating the value stored in ‘num’. This is the pass-by-reference method which was used in C. In C++ there is a different approach. Of course you can use the above method, but C++ has its own special way.

C++ style of Pass by Reference

In the C style we have seen that you need to make use of & and lots of * symbols to pass-by-reference. In C++ we make use of the ‘reference parameter’ (or reference variable) and can avoid the use of so many symbols. All you need to do is put & before your function's parameter.

Example:

void square (&x)

Whatever operation is done on x will actually affect the original calling argument. Basically ‘x’ can be said to be an implicit pointer. The difference is that you needn't use *x to operate on the parameter. Consider the same example:

// Pass by reference C++ style example

void square ( int &x )             // x becomes a reference parameter
{
x = x * x;                     //no need to write *x = (*x) * (*x); as we did earlier
}

int main ( )
{
int num =10;
square(num);                                                     // No need to say &num as we did earlier
cout<<" Value of num is "<<num;                     // Value of a is 100
return 0;
}

The line x = x * x ; actually operates on ‘num’ and not on a copy of ‘num’. When the C++ compiler sees that a function has been declared with its arguments having ‘&’, it knows that the function is a pass-by-reference type.

Reference variables are not applicable only to function parameters. You can have them in other places of the program as well. Consider the following program:

#include <iostream.h>
int main( )
{

int x;
int &ref = x; //ref is a reference variable
x=5;
cout<<endl<<x<<" "<<ref;
x++;
cout<<endl<<x<<" "<<ref;
ref++;
cout<<endl<<x<<" "<<ref;
cout<<endl<<&x<<" "<<&ref;
return 0;

}

The output is:

5 5
6 6
7 7

0x0065FDF4  0x0065FDF4

In the above program ‘ref’ is a reference variable (in other words it is an alternative name for the variable ‘x’). So, if you perform an operation on ‘x’, the value of ‘ref’ will also change and vice-versa. The concept of reference variables is that even though we provide different names to the two variables, they both will refer to the same memory address. In the above program, the address of both ‘ref’ and ‘x’ is the same.

• Usually reference variables will only be used with respect to functions (using them as shown in the program above can lead to confusion). Passing by reference is especially useful in passing structures and objects to functions.
• In the case of structures, if you use pass-by-value, memory space will be used up to create a copy of the structure within the function. Passing the structure by reference will avoid this overhead.
• In the case of classes, if you pass an object by pass-by-value you will be invoking an extra destructor (because a copy of the object is made). In passing an object by reference we can avoid this problem (this will be discussed later).
• References can also be returned by functions (dealt with in operator overloading and in streams).

Can arrays be passed by value?

When we pass arrays to a function we are actually passing the address of the first element of the array. This is as good as passing a pointer to the function. Thus the function will be directly operating on the original array and not on a copy of the array. There is no way of creating a function which when called will operate on a copy of the array (unless you create a new array within the function and manually copy the elements from the original array to the new array).

Test yourself on Pass by Reference

This section is intended to make sure that you've understood pass by reference.
Write a C++ program to get two numbers from the user and swap the values using a function. You have to do it using reference parameters.

The solution will be as follows:

#include <iostream.h>
void swap (int &x, int &y) //pass by reference
{
int t;
t = x;
x = y;
y = t;
}

int main ( )
{
int a , b;
cout<<"Enter the value for a : ";
cin>>a;
cout<<"Enter the value for b : ";
cin>>b;
cout<<"a and b before swap are : "<<a<<","<<b;
cout<<endl;
swap (a,b);
cout<<"a and b after swap are : "<<a<<","<<b;
return 0;
}

Go back to the Contents Page