References in Detail
References and Pointers
A variable can be declared as reference with an & in the declaration. When a variable is declared as reference, it is an alias of an existing variable. Alias means that a variable and its reference can be regarded as the same thing.
Declaring a pointer variable and a reference variable has the same underlying instructions. Both two approaches get the memory address of the existing variable and stores into the declared variable. Similarly, the assembly commands for modifying the value of a memory address through reference or through pointer dereference, are also the same.
Unlike pointer which can be declared without initialization or as a nullptr, a reference variable must be initialized with an existing variable when it is declared. In this way, a reference is safer than a pointer since it can't be NULL.
Besides, these is no multi-level references as pointer does.
Reference plays an important role, especially as function parameters. In the following case, we write a swap function which takes two arguments and swap them. We can make this in using pointers as parameters and pass addresses of arguments inside, but reference makes it in a easier way.
The way we declare reference to an array in kind tricky. We need to add brackets outside the reference variable, which states the priority, and then states the array size with square brackets. It is similar to declaring an array instead of declaring a pointer, since reference is the alias of another variable.
In the above case, the pointer has a size of 4 bytes, and reference has a size of 20 bytes, which is the same as the original array.
Rvalue References
All the cases we've seen now is references of Lvalues. A Lvalue is a type of value that can appears at the left of operator =
. It has a variable name and a memory address that can be modified. On the contrary, a Rvalue doesn't have a variable name nor a memory address. It can only appears at the right of operator =
. We cannot declare a normal reference of a Rvalue.
C++11 introduced many features, one of them is Rvalue references. With two & symbols, we can declare a reference of a constant.
But how can we make a reference to a Rvalue since it doesn't have a memory address? The assembly commands shows the magic. When declaring a Rvalue reference, the compiler creates a temporary variable to store the value of the constant, and then assign the address of that temporary variable to the reference variable.
Alternatively, we can use const
to declare a Rvalue reference as well.
Notice that a Rvalue reference is a Lvalue itself, which means that only Lvalue references can be used to refer to it.
const
, Pointers and References
const
, Pointers and ReferencesNow let's take a look at the following code. Is this code able to be complied or not?
It seems confusing, but we can convert the reference to a pointer to make it clearer. Notice that int &a = b
has the same function as int *p = &b
, so the code above can be converted into follows:
Now the problem is clear since we already discuss about const
and double pointers. The code above actually convert a type of int ** into const int **, which is invalid.
See the post "
const
and Pointers" if you forget it.
Last updated