Thursday, July 24, 2008

REFERENCES

Unlike C, C++ provides true call-by-reference through the use of reference types. A reference is an alias or a name to an existing object. They are simliar to pointers in that they must be initialized before they can be used. For example, let's declare an integer:

int n = 10;

and then declare a reference to it:

int& r= n;

Now r is an alias for n; both identify the same object and can be used interchangeably. Hence, the assignment

r = - 10;

changes the value of both r and n to -10.

It is important to note that initialization and assignment are completely different for references. A reference must have an initializer. Initialization is an operator that operates only on the reference itself. The initialization

int& r = n;

establishes the correspondence between the reference and the data object that it names. Assignment behaves like we expect an operation to, and operates through the reference on the object referred to. The assignment,

r = -10;

is the same for references as for any other lvalue, and simply assigns a new value to the designated data object.

C programmers know that C uses the call-by-value parameter mechanism. In order to enable functions to modify the values of their parameters, pointers to the parameters must be used as the ``value'', which is passed. For example, a routine Swap(), which swaps its parameters would be written like this in C:

void Swap (int* a, int* b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}

The routine would be invoked like this:

int x = 1;
int y = 2;
Swap (&x, &y);

C programmers are all too familiar with what happens when one of the ampersands is forgotten; the program usually ends with a core dump!

Now consider the C++ version of Swap() which makes use of true call-by-reference.

void Swap (int& a, int& b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
}

The routine would be invoked like this:

int x = 1;
int y = 2;
Swap (x, y);

The compiler ensures that the parameters of Swap() will be passed by reference. In C, often a run-time error results if the value of a parameter is passed instead of its address. References eliminates these errors and is syntactically more pleasing.

Another use for references is as return types. Consider this routine:

int& FindByIndex (int* theArray,int index)
{
return theArray[index];
}

Note that the FindByIndex() returns a reference to the element in the array rather than its value. The expression FindByIndex (A, i) yields a reference to the ith element of the array A. Now, because a reference is an lvalue, it can be used on the left hand side of an expression, we can write:

FindByIndex(A, i) = 25;

which will assign 25 to the ith element of the array A.

Note that if FindByIndex() is made inline, the overhead due to the function call is eliminated. Inline functions that return references are attractive for the sake of efficiency.

No comments: