References are pointers that are always initialized in
their declarations to some existing object, and cannot be re-assigned to point
to other objects. They will always be dereferenced when used, so their usage
differs from pointers in their syntax. The formal description of their usage
is:
<type> ‘&’
<identifier> ‘=’ <object of the specified type> ;
Examples:
int a = 7;
int &ra = a;
ra++; // Now a is 8.
The integer is incremented, not the pointer
This is a reference to an integer that is initialized to
point to the address of the integer ‘a’. Note that you should not specify the
address-of operator, as you would do with a normal pointer. It is the compiler
that internally takes the address of the resulting object.
· References cannot be re-assigned. Any re-assignment of a reference is a compilation error. The only exception is the initialization of a reference when it is declared or when the declaration includes an explicit external keyword.
· In an external reference, the type of the reference must be explicitly known to the compiler when the reference is first used, since to dereference an object (and references are always dereferenced when used) the compiler must know its definition.
· A function that expects a reference cannot receive a pointer. Pointers and references are not compatible and no automatic conversion between pointers and references is provided. To convert a reference to a pointer, use the address-of operator (‘&’).
· Tables of references are not possible.
· Pointer arithmetic is not possible with references.
· References of references are not possible.
· The initialization of a reference should always follow the declaration, unless the declaration is a function argument or a function result.
· Arrays of references are not possible.
· A reference cannot be assigned to a bit-field.
· The address of a reference cannot be taken, since the address-of operator will be applied to the object to which the reference points. In the example above, the expression &ra means the address of the object ra points to the integer a. The result will be the address of a and not the address of the reference.
· Since the address of a reference cannot be taken, there can be no pointers to references.
· In a function call to a function, which has a reference as argument in its prototype, the reference and not its value will be passed.
· In a function call to a function with no prototype or with one that does not have a reference in the given position, the value pointed to by the reference will be passed.
· In a return statement, when the function has a reference as return value, the compiler automatically takes the address of the resulting object, and returns this reference as the result of the function.
In C++, passing arguments by reference avoids calling the
automatic constructors and destructors for the object. Since there are no
destructors or constructors called automatically here, the need for references
is less pronounced. C is not C++, and there are no functions being called
‘behind your back’ by the compiler. All implicit function calls are those
redefined explicitly by the program.
Examples:
Given
int fn(int &arg)
{
return arg+8;
}
You cannot use:
fn(6);
for instance. A constant is not automatically converted to
a reference. This is consistent with the C++ behavior.
[1] This construct is needed by the problem of the
operator [ ]. To avoid having the construct Vector[5] = 6; be forced to be
written as *Vector[5] = 5; or add a new operator [ ]= incompatible with the C++
language, I decided to add the references to lcc-win32. This has ancillary
benefits because in general, references are cleaner than pointers: you can do
fewer things with them. Since they always have to be initialized to a known
object, there is less room for error.
[2] These rules are the same as in the C++
language.