A reference is just giving another name to an existing object or variable. Whereas a pointer is a variable that stores the address of another object.

There is nothing we can do with the references that we cannot do with pointers. Both are almost the same with just a syntactic difference.

Following is some of the major differences between pointers and references:

  1. A pointer can be re-assigned but references cannot be re-assigned and must be bound at the time of initialisation.
/* =====>  Pointers  <===== */

int a = 10;
int b = 20;

// Pointer is not initialized
int *p;

// Can be assinged later
p = &a;

// Can also be re-assigned
p = &b;
/* =====>  References  <===== */

int a = 10;
int b = 20;

// Must be bound to an object at the time of initialisation
int& ref = a;

// Cannot be re-assinged to another object later
// Following statement overrides 10 in variable 'a' with 20;

ref = b;

2. Every pointer variable has its own address (identity) and it can be fetched with a unary (&) operator.

Using the unary (&) operator on references returns the address of an object to whatever the reference variable is bound to. It is better to think that references are just giving another name to an existing object.

int var = 10;
int* ptr = &var;
int& ref = var;

std::cout << "Address of var = " << &var << std::endl;
std::cout << "Address of ptr = " << &ptr << std::endl;
std::cout << "Address of ref = " << &ref << std::endl;


/* Ouput */
Address of var = 00FCFD2C
Address of ptr = 00FCFD20
Address of ref = 00FCFD2C

3. We often use pointers as nested pointers where one pointer points to another pointer which offers extra levels of indirection using multiple (*) operators.

Whereas references offer only one level of indirection.

int var = 10;

int* ptr = &var;
int** ptr2 = &ptr;

// Multi level indirection is possible with pointers
**ptr2 = 20;

std::cout << var << std::endl;

4.  A pointer can be assigned to nullptr when we don't have an object to point it to. Whereas it is illegal to assign nullptr to a reference. It must be always initialized with a valid object.

// Valid to use
int* p = nullptr;

// Throws compilation error
int& ref = nullptr;

5. Array of references are not allowed and also we cannot point a reference to an array. Whereas it is allowed to point a pointer to an array and can perform arithmetic operations on a pointer to jump to the next or previous indexes.

int a[5] = { 1,2,3,4,5 };

// Cannot point a reference to an array
int& ref = a; 

// Array of references are not allowed; compilation error
int& ref2[5] = a;


/* Allowed to point to an array */
int *ptr = a;

/* Allowed to create array of pointers */
int *ptr2[3];

6. We need to use (*) to access the value of an object that a pointer points to. Whereas a reference can directly access it.

When using struct/class pointers use -> operator to de-reference whereas reference use (.) operator to de-reference.

7. We can bound constants to a const reference where pointers cannot be bound to constants.

const int& ref = 10;

// not allowed; compilation error
int *p = 10;

Let's write a program to swap two numbers using both the pointers and references so that you will understand the difference between them.

Using pointers:

#include <iostream>

/* Using references, we are directly modifying the values of a & b */

void swap(int* a, int* b) {

	int temp = *a;
	*a = *b;
	*b = temp;
}

int main() {
	int a = 10;
	int b = 20;

	printf("Before swap -> a = %d, b = %d \n", a, b);
	swap(&a, &b);

	printf("After swap -> a = %d, b = %d \n", a, b);
	return 0;
}

Using References:

#include <iostream>

/* Using references, we are directly modifying the values of a & b */

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

int main() {
	int a = 10;
	int b = 20;
    
	printf("Before swap -> a = %d, b = %d \n", a, b);
	swap(a, b);

	printf("After swap -> a = %d, b = %d \n", a, b);
	return 0;
}

The output of both the programs is the same but the way how we did it with references is different than pointers.

References in C++ with example
A reference is just giving another name to an existing object or variable. There is nothing we can do with references that we cannot do with...