Breaking down pointers (in C++)
A short, concise takeaway on pointers using C++ as a case study
I recently began learning C++ (or CPP), a powerful language built on C. C++ is a language that exposes a lot more than conventional languages like JS, Python and Java. Having worked with weird languages (like Rust) and language for dummies (Golang), a lot of that knowledge was easily transferable to C++. But there were still some grey areas where I didn't fully understand what was happening under the hood. Taking a cue from one of my mentors Tiger Abrodi, I am now writing those grey areas as I learn and attempting to simplify them for myself and you, the reader.
The first concept I would be writing about is pointers. What are pointers?
๐ Pointers
A pointer is a variable that stores the reference to another variable. A variable is named object. What's an object? An object is a region of memory with a type that specifies what kind of information can be placed in there. The type here refers to int
, double
, char
, etc. Think of an object as a box, where you can only put a certain type of item (jackets, for example). If you label the box, it becomes a variable.
Pointers are simply what I like to refer to as middlemen or contacts. Using the box analogy from the last paragraph, let's imagine the box is in a room. A pointer would be a person standing in the room and pointing to the box. The room is your computer memory, the location of the box in the room is the address or memory address of "jacket box" (what we are calling the box), and the person pointing is the pointer.
We could enter the room and directly head over to the box to get, change or even remove its contents. That is the normal declaration and assignment we are used to.
int a = 5;
a = 6;
// print a
std::cout << a; // 6
Alternatively, we could head over to the person pointing, and following their direction (the pointing finger), locate the box. Recall what we said earlier? A pointer stores the reference to another variable. We could also say a pointer stores the memory address of another variable. Using that, we can also define a pointer as: "A data type that can store memory addresses".
Going back to the room analogy, one thing to note is that the person pointing to the box is also inside the room. Not outside. It is also a variable stored in memory. Going back to the first definition of pointers, a pointer is an unusual variable. Other variables store a number or a character, a pointer stores the location of another variable!
int num = 8;
int* ptr = #
cout << ptr << endl;
cout << *ptr << endl;
In C++, the *
is one of the ways to declare a pointer type. This is interpreted as a variable that would store (point to) the memory address of an int
type. The &num
is a notation to get the memory address of a variable itself. We then printed out ptr
, which would give us a weird string (like 0x7ffeee679d4c8
). That weird string is the address of num
in the memory, if we were to head here (whilst the program is running), we would find num
!
What happens if we print
&num
? It prints out the same memory address as our pointer. That's because the pointer stores the memory address, and the reference operator (&
) also returns the memory address of that variable.
The last line (*ptr
) is called the "dereference operator". Dereferencing is trying to get the value of the memory address pointed to by our pointer. Using the room analogy, instead of just giving me the location of the box, we are asking the person what is stored at that location. In this case, a handful of jackets! Don't forget, the box is the holder of the jacket, it isn't the actual item stored in that location.
At the start, I also mentioned that pointers are middlemen. What do I mean by that? A pointer isn't tied to what it points to. It can point to something else, or even nothing at all! (Null pointers ๐). Remember, a pointer is a variable that stores the memory address of others. Like any other variable, it can be re-assigned (pointed to something else)
int num = 10;
int let = 20;
// ptr initially points to num
int* ptr = #
// Reassign ptr to point to let instead
ptr = &let;
๐ Pointers vs Reference
Something I tended to gloss over was the difference between a reference declaration and a pointer. They are very similar in what they do but are two very different things.
What does a reference mean here? A reference is an alias for an already declared variable. Let's re-use the room analogy. A reference would simply be slapping another label on the box. We originally called the box "jacket box", that is the name. A reference is simply a "reference to that variable", let's call it "jacket ref" (short for reference).
References do not take up additional space in memory. It is simply just an "alias".
int num = 5;
int& alias = #
The int&
means "a reference to type int
". Notice how we are assigning it to the memory address of num
and not the value of num
. If we were to print out alias
and num
, they would both be 5. If we were to modify the value of alias
, it would modify the value of num as well.
int num = 5;
int& alias = #
alias = 10;
cout << "Alias is: " << alias << "\nNum is: " << num;
They would both print 10. Using the room analogy, we just added a second label to the box. If we walked into the room looking for "jacket ref", we would still head over to the same box. So, what would happen to the "jacket box" if we were to change the jackets in the "jacket ref" box? The same thing because they are the same box!
By the way, this is the basis of pass-by-reference in languages that utilise it like Java, Rust and C++.
What about pointers? A pointer can do the same thing
int num = 6;
int* ptr = #
*ptr = 8 // num becomes 8
OK, what just happened? As we can change the address a pointer stores (points to), we can also change the content of what is stored in that address. Using the same old room analogy, this is the same as the person pointing and reaching over to add, change or remove jackets from the box.
What are some of the main differences?
Pointer | Reference |
A pointer is a variable stored in memory. It stores the address of another variable | A reference is an alias for another variable. It's not a new one, just another name for an existing one. |
Can be reassigned to point to other objects. | Can not be re-assigned to another variable. |
Can be null (pointing to nothing) | Cannot be null. It must be initialized to something. |
Pointers have their memory address (they're stored in memory after all) | References don't occupy any additional space beyond the referenced variable. |
You can have pointers pointing to another (Remember, they are storing memory addresses after all) | References cannot reference another reference |
Based on the current article, can you figure out what this meme implies ๐
That's it for this article! I hope to write more as I learn more, blog driven development is a wild, yet effective method of learning and I am committed to putting pen to paper when I have something of note. I am also building simple, public projects on my GitHub using C++, trying to put what I learn into practice, you can check me out @ShafSpecs.
I also enjoy this analogy and simple writing format. Makes things easier for me when revising notes, hope you enjoyed it too! If you have any tips, comments or corrections, please drop them down below. Till next time ๐!