Before I start explanations, I have to note, that exact address values for variables used in the examples in this article can be different, because they may depend on machine memory architecture and used OS.
References – the very basic explanation
Reference is operator (address-of operator), used in expression produces address in memory where a variable value is stored.
and can be used like in the below example:
int distance = 5; cout << "address of variable: " << &distance << endl; // result: 0x7ff7bfc3f918
The important thing to know is the fact, that address where value of a variable is stored is out of scope – it is always available from any place in code. It means, for example, that you can modify value of an external variable from inside a function, that is from place where usually you don’t have access to external variables. To make it possible we pass variables to functions in way called pass-by-reference, using the & operator, instead pass-by-copy (the “standard” way). In such case, in function declaration, operator & is used to declare reference variable, that is alias to an existing variable. Below is an example how function with pass-by-reference can look like, very primitive example, just to give you an idea:
//function declaration void square(int &); //and implementation void square(int & aNumber) { aNumber *= aNumber; //aNumber value outside the function has just been changed }
Pointers – the very basic explanation
In C++ a pointer is just a variable, however it can store only one kind of data: memory address. For instance, pointer can store memory address of another int variable. In other words, having address of some place in memory pointer points to some location in memory.
Pointer can be initialized or uninitialized, and it should be initialized before it is used to avoid memory issues. If you know what pointer should store, you can initialize it straight away. For instance, we would like pointer distance_ptr to store address of variable distance.
int distance = 5; int *distance_ptr = &distance; cout << "distance pointer: " << distance_ptr << endl; // result: 0x7ff7bfc3f918 cout << "distance pointer, dereferenced: " << *distance_ptr << endl; // result: 5
With operator * pointer can be dereferenced, that is it can show value stored at given memory address, as seen in the above example.
We have to remember that pointer can change its value, but cannot change data type it stores. So, pointer declared as int should always keep address of int variable, pointer declared as string pointer, should store address of string variable and so on.
Pointer points to location in memory space, and what is in the location can change (variable can change its value), but pointer value stays always the same, as long as address of the memory location assigned to the pointer stays the same.
Pointer should always be initialized. Uninitialized pointer stores to some unpredictable address location in memory, and using such pointer can produce unpredictable issues. If we don’t know what value pointer should store, it is always safe to initialize it with null value, like in the below example.
string *height_ptr {nullptr}; cout << "height_ptr pointer: " << height_ptr << endl; // result: 0x0
We can say, that uninitialized pointer points to anywhere (dangerous – can be location where system stores important data), and pointer initialized with null value points to nowhere, and the nowhere 0x0, which represents address 0 (zero) is a safe option.
Pointers and references as used in C++ are very advanced tools for memory management and are one of reasons why C++ can be very fast. Despite the fact, that many people thinks that are not safe, they are safe as long as you know exactly what you do. In higher level languages like for instance C# pointers are not explicitly available.
Pointers – areas of confusion
1. It is good to know, that character * used for pointers declarations can be used in 3 different ways, and all are correct:
int *distance_ptr{nullptr}; int* distance_ptr{nullptr}; int * distance_ptr{nullptr};
2. What we have here:
cout << "distance pointer, dereferenced: " << *distance_ptr << endl;
is pointer de-reference, not pointer declaration, in other words, in the above line we get out variable value stored at the variable address.
References – areas of confusion
In the below line operator & takes address of a variable, but in the line lower it means passing variable by reference in function, which allows a function to modify the variable, without creating its copy.In other words – here we pass not a variable, but the variable’s reference (alias):
cout << "address of variable: " << &distance << endl; void square(int & aNumber) {