When we write
1 2 3 4 5 6 7
|
int i = 0 ;
int main()
{
int j = 99 ;
i = j ;
}
|
i
and
j
are names of two objects of type int. Each name has a binding to a location in memory. The compiler knows all about this binding; for
i = j ;
, the code it generates is logically equivalent to: pick up the int which is at the memory location identified by the name
j
and write that value into the int at the memory location identified by the name
i
.
For objects with a dynamic storage duration, the compiler has no idea where these objects are in memory; we can't ask the compiler to map a name to the memory location for such an object (unless we also tell it where it is in memory).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
int i = 0 ;
int main()
{
int* pointer = new int(99); // the anonymous int is at the address contained in 'pointer'
// once we have the address, if we want, we can create an alias for the unnamed object.
// in effect we tell the compiler: there is an object of type int at the address contained in pointer.
// from now on, when we say 'name' we mean this object
const int& name = *pointer ;
i = *pointer ; // assign the value of the unnamed int whose address is in 'pointer'
//to the int identified by 'i'
i = name ; // assign the value of the int identified by 'name' to the int identified by 'i'
}
|
EDIT: An array is closely associated with a pointer (which holds the address of a memory location) for the same reason:
int array[20] ;
- we have 20 objects of type int, but we do not have a name for each of them.
array[5] ;
- the anonymous object which is at a memory location 5 'ints' away from the object right at the beginning of the array.
array
decays to a pointer to object at position 0, the memory location of the other objects in the array can be specified relative to the memory location of the object right at the beginning.