References in C++

When a variable is declared as a reference, it becomes an alternative name for an existing variable. A variable can be declared as a reference by putting ‘&’ in the declaration. 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include<iostream>
using namespace std;
 
int main()
{
  int x = 10;
 
  // ref is a reference to x.
  int& ref = x;
 
  // Value of x is now changed to 20
  ref = 20;
  cout << "x = " << x << endl ;
 
  // Value of x is now changed to 30
  x = 30;
  cout << "ref = " << ref << endl ;
 
  return 0;
}

chevron_right


Output: 

 x = 20
ref = 30

Applications :  

  1. Modify the passed parameters in a function: If a function receives a reference to a variable, it can modify the value of the variable. For example, the following program variables are swapped using references. 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include<iostream>
using namespace std;
 
void swap (int& first, int& second)
{
    int temp = first;
    first = second;
    second = temp;
}
 
int main()
{
    int a = 2, b = 3;
    swap( a, b );
    cout << a << " " << b;
    return 0;
}

chevron_right


Output:

 3 2 

1. Avoiding a copy of large structures: Imagine a function that has to receive a large object. If we pass it without reference, a new copy of it is created which causes wastage of CPU time and memory. We can use references to avoid this.



CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

struct Student {
   string name;
   string address;
   int rollNo;
}
 
// If we remove & in below function, a new
// copy of the student object is created.
// We use const to avoid accidental updates
// in the function as the purpose of the function
// is to print s only.
void print(const Student &s)
{
    cout << s.name << "  " << s.address << "  " << s.rollNo;
}

chevron_right


2. In For Each Loops to modify all objects : We can use references in for each loops to modify all elements 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    vector<int> vect{ 10, 20, 30, 40 };
 
    // We can modify elements if we
    // use reference
    for (int &x : vect)
        x = x + 5;
 
    // Printing elements
    for (int x : vect)
       cout << x << " ";
 
    return 0;
}

chevron_right


3. For Each Loop to avoid the copy of objects: We can use references in each loop to avoid a copy of individual objects when objects are large.  

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    vector<string> vect{"geeksforgeeks practice",
                     "geeksforgeeks write",
                     "geeksforgeeks ide"};
 
    // We avoid copy of the whole string
    // object by using reference.
    for (const auto &x : vect)
       cout << x << endl;
 
    return 0;
}

chevron_right


References vs Pointers:

Both references and pointers can be used to change local variables of one function inside another function. Both of them can also be used to save copying of big objects when passed as arguments to functions or returned from functions, to get efficiency gain. Despite the above similarities, there are the following differences between references and pointers.

1. A pointer can be declared as void but a reference can never be void For example

int a = 10;
void* aa = &a;. //it is valid
void &ar = a; // it is not valid

Thanks to Shweta Bansal for adding this point.

2. The pointer variable has n-levels/multiple levels of indirection i.e. single-pointer, double-pointer, triple-pointer. Whereas, the reference variable has only one/single level of indirection. The following code reveals the mentioned points:  



C++

filter_none

edit
close

play_arrow

link
brightness_4
code

#include <iostream>
using namespace std;
 
int main() {
    int i=10; //simple or ordinary variable.
    int *p=&i; //single pointer
    int **pt=&p; //double pointer
    int ***ptr=&pt; //triple pointer
    // All the above pointers differ in the value they store or point to.
    cout << "i=" << i << "\t" << "p=" << p << "\t"
         << "pt=" << pt << "\t" << "ptr=" << ptr << "\n";
    int a=5; //simple or ordinary variable
    int &S=a;
    int &S0=S;
    int &S1=S0;
    cout << "a=" << a << "\t" << "S=" << S << "\t"
         << "S0=" << S0 << "\t" << "S1=" << S1 << "\n";
    // All the above references do not differ in their values
    // as they all refer to the same variable.
 }

chevron_right


 References are less powerful than pointers
1) Once a reference is created, it cannot be later made to reference another object; it cannot be reseated. This is often done with pointers. 
2) References cannot be NULL. Pointers are often made NULL to indicate that they are not pointing to any valid thing. 
3) A reference must be initialized when declared. There is no such restriction with pointers
Due to the above limitations, references in C++ cannot be used for implementing data structures like Linked List, Tree, etc. In Java, references don’t have the above restrictions and can be used to implement all data structures. References being more powerful in Java is the main reason Java doesn’t need pointers.
References are safer and easier to use: 
1) Safer: Since references must be initialized, wild references like wild pointers are unlikely to exist. It is still possible to have references that don’t refer to a valid location (See questions 5 and 6 in the below exercise ) 
2) Easier to use: References don’t need a dereferencing operator to access the value. They can be used like normal variables. ‘&’ operator is needed only at the time of declaration. Also, members of an object reference can be accessed with dot operator (‘.’), unlike pointers where arrow operator (->) is needed to access members.
Together with the above reasons, there are few places like the copy constructor argument where pointer cannot be used. Reference must be used to pass the argument in the copy constructor. Similarly, references must be used for overloading some operators like ++.
Exercise: 
Predict the output of the following programs. If there are compilation errors, then fix them.
Question 1 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include<iostream>
using namespace std;
 
int &fun()
{
    static int x = 10;
    return x;
}
int main()
{
    fun() = 30;
    cout << fun();
    return 0;
}

chevron_right


Question 2 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include<iostream>
using namespace std;
 
int fun(int &x)
{
    return x;
}
int main()
{
    cout << fun(10);
    return 0;
}

chevron_right


Question 3 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include<iostream>
using namespace std;
 
void swap(char * &str1, char * &str2)
{
  char *temp = str1;
  str1 = str2;
  str2 = temp;
}
 
int main()
{
  char *str1 = "GEEKS";
  char *str2 = "FOR GEEKS";
  swap(str1, str2);
  cout<<"str1 is "<<str1<<endl;
  cout<<"str2 is "<<str2<<endl;
  return 0;
}

chevron_right


Question 4 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include<iostream>
using namespace std;
 
int main()
{
   int x = 10;
   int *ptr = &x;
   int &*ptr1 = ptr;
}

chevron_right


Question 5 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include<iostream>
using namespace std;
 
int main()
{
   int *ptr = NULL;
   int &ref = *ptr;
   cout << ref;
}

chevron_right


Question 6 

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

#include<iostream>
using namespace std;
 
int &fun()
{
    int x = 10;
    return x;
}
int main()
{
    fun() = 30;
    cout << fun();
    return 0;
}

chevron_right


Related Articles : 

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up