Home C++ Introduction Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess STL Modern C++ Misc Books ----

References



References allow us to define another name for an existing variable.

File: ref1.cpp
#include <iostream>
using namespace std ;

int main()
{
    int x1 = 5 ;
    int& ref1Var  = x1 ;
    cout << ref1Var << endl ;
    ref1Var++ ;
    cout <<x1 << " : " <<  ref1Var << endl ;
    x1++ ;
    cout <<x1 << " : " <<  ref1Var << endl ;
    //Every reference need to be initialized at the point of definition.
    //Compiler error
    //   int& refVar1 ;
    return(0)  ;

}
$ ./a.exe
5
6 : 6
7 : 7
A reference is defined as "&variableName". The variable that it refers to must be assigned at the time of definition. Changing "ref1Var" changes the original variable. Chaning the original variable's value also causes x1's value to be changed. The reference is another name for the variable "x1" .

In the above example we declare a reference variable with the declaration :

int& refVar1 = x1 ;

We do need to have the reference variable refer to something. In this case it refers to the integer variable x1. We print the value of "refVar1" :

cout << ref1Var << endl ;

The value printed is "5" since ref1Var is another name for x1. We increment "ref1Var" with the statement:

ref1Var++ ;
cout <
The "ref1Var" increments "x1" also since they refer to the same thing. Thus the values printed out are 6 and 6 .
Similarly when we increment "x1" then we get 7 and 7 printed out for the 2 variables. The variables refer to the same thing. A reference can be thought of as a handle to the existing variable. When we declare a reference we need to provide an existing variable for it. Just declaring it as:

int& refVar1 ;

inside a function will produce a compiler error. Normally when we pass variables to arguments in functions they are passed by value.
File: ref2.cpp
#include <iostream>
using namespace std ;
//Pass by reference instead of pass by value
//Advantages of pass by reference
//-----------------------------------------------


void func1( int param1 )
{
    param1  = 200 ;
}
//------------------------------------------------

int main()
{
    int  local1 = 100 ;
    func1( local1 ) ;
    cout << local1 << endl ;
    return(0)  ;
}
//-------------------------------------------------
Output:

[amittal@hills References]$ ./a.out

100
The function "func1" is called but as we can see the value of the variable "local1" does not get changed. The variable is not passed when the function is called. Rather the value of the variable is passed and then copied to the "func1" local parameter. The parameter "param1" definition starts when we enter the function and the value of 100 is copied to it. Then the value of "param1" is changed to 200 and then the function ends. The variable "param1" now goes out of scope. Calling the function does nothing to change the original value of the variable "local1". Let's see how we can use references to enable a function to change the value of it's argument.
File: ref3.cpp
#include <iostream>
using namespace std ;

//Pass by reference instead of pass by value
//Advantages of pass by reference

//--------------------------------------------------------------------
void func1( int& param1 )
{  
param1  = 200 ;
}
//--------------------------------------------------------------------i

nt main()
{   
 int  local1 = 100 ;    
 func1( local1 ) ;     
 cout << local1 << endl ;
 return(0)  ;

}
//--------------------------------------------------------------------


[amittal@hills References]$ ./a.out

200
The function declaration is now of the form:

void func1( int& param1 )

The parameter "param1" is declared as a reference. What is it pointing to right now. Nothing really. It comes into action when it is called.

func1( local1 ) ;

When the function is called the local1 variable is passed but not by value. Rather the function reference "param1" now points to the variable local1. The word "points" should not be confused with the concept of pointers. Now when the statement is executed:

param1 = 200 ;

It changes the value of the "local1" in main. This is useful when objects are concerned as an object may be very large and when calling a function the object's values will not be copied but rather the reference will point to the original object.
References allow us to place a function call at the left hand side of the assignment statemen

File: ref4.cpp
#include <iostream>
using namespace std ;

//Using references to let a function be a l value
//--------------------------------------------------------------------

int global1 ;
int& func1( )
{
  return global1 ;
}

//--------------------------------------------------------------------

int main()
{
    global1 = 100 ;
    func1()    = 200 ;
    cout << global1 << endl ;

    return(0)  ;
}
In the above example the function "func1" returns a reference to the global variable "global1" . The statement

func1() = 200 ;

actually changes the variable "global1" to the value 200. In this case we do not have a name for the reference.

We know that the function "func1()" will return a reference to the variable "global1" . This situation can have it's pitfalls. Ex:
File: ref5.cpp
#include <iostream>
using namespace std ;

//Using references to let a function be a l value
//--------------------------------------------------------------------

int& func1( )
{
  int x1 ;
  return x1 ;
}

//--------------------------------------------------------------------

int main()
{
    func1()    = 200 ;
    return(0)  ;
}
Output:

[amittal@hills References]$ ./a.out

Segmentation fault (core dumped)
Why did the program fail ? The function "func1" returns a reference to the local variable "x1". However when the function ends the variable falls out of scope. By the time we try to assign the value of 200 to it the memory location is not valid and we get a "Segmentation fault".

The ability to have a function call on the left hand side has it's uses in certain cases. In C++ we can overload operators . One of the operators that can be overloaded is the subscript operator "[]" . Let's say we wanted a class whose objects could be accessed by the subscript operator and we wanted the ability to change the value of our data structure.

someObj[1] = 3 ;

The following class shows an example of how to use this.


File: ref6.cpp
#include <iostream>
using namespace std ;

//Using references to let a function be a l value
//Use case
//--------------------------------------------------------------------

class myVector
{
  public:
   int x1 ;
   int array1[]  ;
    myVector():  array1{ 1, 2, 3 }
    {

    }

    int& operator[] (int index)
        {
          return array1[index]  ;
        }

};

//--------------------------------------------------------------------

int main()
{
    myVector myVectorObj ;
    cout << myVectorObj[0] << endl ;
    myVectorObj[0] = 100 ;
    cout << myVectorObj[0] << endl ;
    return(0)  ;
}

//--------------------------------------------------------------------


We can also have a reference pointing to another reference.
File: ref7.cpp
#include <iostream>
using namespace std ;

//--------------------------------------------------------------------
int main()
{
   int x1 = 100 ;
   int& ref1 = x1 ;
   int& ref2 = ref1 ;

   cout << x1 << " " << ref1  << " " << ref2 << endl ;

   return(0)  ;
}


Output:

100 100 100