Hi, and welcome back to the course about pointers in C++.
My name is Mateo, and in this module, we'll discuss another important use case
for pointers, dynamic memory allocation. In the previous module, we learned that
every place in memory has its own memory address.
So when we declare a variable,
a place in memory is allocated to store its contents.
Of course, place is not an official term, it is just an abstraction that I
chose to use to explain the concepts from the previous module, and in most
cases, this abstraction is good enough because, after all, memory address
is really tied to a place in memory.
However,
some parts of the course will require us to go a
little bit more lower level than this,
especially the next module where we'll discuss pointer arithmetic and arrays.
So before we learn about the dynamic memory allocation,
I want to revisit pointer data types. In the previous module, we said that the
data type in the pointer declaration needs to match the data type of the
variable that this pointer will be pointing to, but why?
To answer this question, I prepared a small demonstration.
I am using the size of operator to get back the amount of memory that
needs to be allocated for each one of these data types.
The operator will output the amount of bytes needed to
store a variable with the given data type.
So as you can see, if you want to create an integer variable, the
program will need to allocate 4 bytes of data, which is the usual
size of an integer on most systems.
This number could be different on your computer
because it depends on multiple factors, but it doesn't matter.
The point of this program is to show you that every data type requires
different amount of bytes in memory. To store a double,
you will need 8 bytes, and to store a character, you
will only need 1 byte of memory.
Now let me add an asterisk to each one of these data
types to turn them into pointers.
So instead of asking how big is an integer, double, or a char, I'm asking
how big is the pointer to an integer, pointer to a double, and a pointer
to a char value? Let's compile this. Now,
this is interesting.
We used three different pointer data types, but they all seem to have the
same size, which is 8 bytes, and if you think about it,
this makes sense because we said that pointers store a memory address and this
address is just a number so it doesn't matter if there is an integer, double,
char, or some other complex object at this address.
The address itself is still just a number,
just like a street number of a house is just a number
no matter how big the house is.
The reason this number requires 8 bytes is because memory in
64‑bit architectures need 64 bits to store the highest memory
address and 64 bits is 8 bytes.
If you are working on a 32‑bit system,
the pointers will allocate 4 bytes instead of 8.
So if all of these pointers need the same amount of memory,
why do we even need these data types?
Since memory is made up of a large amount of bytes, that means that each
one of those bytes has its own memory address. In the previous module, we
said that a place in memory needs to be allocated for each variable, but
the question is how big is this place?
If we declare a double variable, we'll need to allocate 8 bytes, but if we
declare an integer, we'll only need 4 bytes so this abstraction we used will
need to be expanded. Instead of saying that each place in memory has an
address, we need to think about memory as a series of bytes so each byte in
memory has its own address.
With this new insight in mind, let's revisit this simple program.
I want to declare an integer variable which means that the
program will need to allocate 4 bytes of memory.
And now let's say that I want to use the address of
operator to get the address of this variable.
Since each 1 of these 4 bytes has its own address, which one do
you think will be returned by the operator?
The returned address will be the address of the first byte in a row, the
starting byte so to say. If I create a pointer which will point to this
variable X, the same address will be stored inside of it.
Of course, we will need 8 bytes of memory to store the pointer
itself so let's do this for the sake of completeness, but we
don't care about that in this lesson.
And now let's say that I want to dereference this
pointer to get the value from variable X.
The reference operator will now look up the address from the
pointer, which is the memory address of this first byte, but
this is not enough information.
We also need these following 3 bytes to correctly read the value from
memory and this is where the pointer data type comes in.
This is why we need them.
If we stored memory address as simple numbers, the compiler
would only know the address of the first byte.
However,
once dereferencing happens, compiler will take a look
at the data type of the pointer.
Since the data type of this pointer is an integer, compiler
will know that it also needs to read the following 3 bytes to
get the correct number from memory.
This will also be useful when we start talking about pointer arithmetic in the
next module. Data types, in general, are just there to provide a useful
abstraction for us humans. The computer sees everything in zeros and ones
anyway. If this seems complicated, don't worry, you will rarely have to think
about memory in this way since C++ does all of the heavy lifting anyway, but
bear this in mind as we go on with the course because we will need it for some
of the other lessons.