References in C++


A reference in C++ is an alias for another object. It can appear wherever the object it refers to can. The following program uses the reference iref as a substitute for i:

/* ref1.c:     Illustrate references */
#include <stdio.h>

main()
{
int i = 10;
int &iref = i;  // An alias for i

printf("%d\n",iref);
iref = 20;
printf("%d\n",i);
return 0;
}

/* Output:
10
20
*/
You can think of a reference as a "smart" pointer, since it refers to another object without requiring explicit addressing and dereferencing like pointers do:

/* ptr.c: Do the same thing with pointers */
#include <stdio.h>

main()
{
int i = 10;
int *iref = &i;

printf("%d\n" ,*iref);
*iref = 20;
printf("%d\n",i);
return 0;
}
The major differences between a pointer and a reference are:

Like pointers, however, references can be function return values. Since a reference is by definition an lvalue, this allows the unusual practice of placing a function call on the left-hand side of an assignment:

/* ref2.cpp:   Returning a reference */
#include <stdio.h>

int & current();    // Returns a reference

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

main()
{
current() = 10;
index = 3;
current() = 20;
for (int i = 0; i < 4; ++i)
   printf("%d ",a[i]);
putchar('\n');
return 0;
}

int & current()
{
return a[index];
}

/* Output:
10 1 2 20
*/
Another use for references is to implement pass-by-reference semantics, meaning that changes to function parameters persist in the calling procedure after the called function returns. You can do this with pointers, but references are cleaner:

/* ref3.cpp:   Swap via references */
#include <stdio.h>

void swap(int &, int &);

main()
{
int i = 1, j = 2;

swap(i,j);
printf("i == %d, j == %d\n",i,j);
return 0;
}

void swap(int &x, int &y)
{
int temp = x;
x = y;
y = temp;
}

/* Output:
i==2, j == 1
*/
Even if you aren't going to modify a function parameter, it is a good idea to pass large objects by reference for efficiency. For example, if the data type X is large:

struct X
{
   // lotsa stuff
};
then a function f that takes a parameter of type X, but doesn't modify it, should have a prototype similar to

void f(const X&);
For a more complete treatment of references, see Dan Saks' column in the September 1991 issue ("Reference Types", CUJ Vol. 9, No. 9).