Pointers & References
Why Do We Need Pointers and References?
In the previous chapters, we learned that:
- programs store data in memory,
- memory locations have addresses,
- the stack manages function calls,
- the heap stores dynamically allocated data.
Now consider this:
How can one piece of data refer to another piece of data?
This is where pointers and references become important.
They allow a program to work with data indirectly rather than always working with the data itself.
This idea is fundamental to many data structures:
Linked List ↓Tree ↓Graph ↓Dynamic data structuresIf you understand pointers and references well, these structures become much easier to visualize.
What Is a Memory Address?
Every addressable location in memory has an address.
Address Value 0x1000 420x1004 170x1008 91Suppose the value 42 is stored at 0x1000. Then the value tells us what is stored, and the address tells us where it is stored.
This distinction is the foundation of pointers.
What Is a Pointer?
Definition
A pointer is a variable that stores the memory address of another value or object.
Instead of storing the actual data, a pointer stores information about where that data can be found.
So a pointer stores an address, and that address points to data. That is why it is called a pointer: it points to another location.
Pointers in C++
C++ gives us direct access to pointers.
int score = 100;int* p = &score;Here score holds 100, and p holds the address of score.
The & operator gets the address of score. The * in int* p declares p as a pointer to an integer.
The pointer does not contain 100. It contains the address where 100 is stored.
Dereferencing a Pointer
Knowing an address is useful only if we can use it to access the value stored there. This is called dereferencing.
int score = 100;int* p = &score; cout << *p; // 100The *p means: go to the memory location stored inside p and access the value there.
p↓0x1000↓memory at 0x1000↓100So there are two different operations:
&score → address of a variable*p → value at the address stored in a pointerBe careful: the meaning of * depends on where it is used. In int* p it declares a pointer. In *p it dereferences one.
Changing Data Through a Pointer
A pointer can also be used to modify the value it points to.
int score = 100;int* p = &score; *p = 200; // score is now 200Why? Because p points to the memory location containing score. The pointer gives us another way to access the same data.
Multiple Names, One Value
Consider:
int score = 100;int* p = &score;Now both score and *p access the same value.
┌─────────┐score ───→│ 100 │ └─────────┘ ↑ │p ────────────┘There is still only one value. There are simply two ways to reach it.
This idea becomes extremely important when working with linked lists, trees, and graphs.
What Is a Reference?
Pointers are not the only way to refer to existing data. Many languages provide references.
Definition
A reference is another name or handle used to access an existing value or object.
Unlike a pointer, a reference is generally designed to be used as an alias rather than as an explicitly manipulated memory address.
For example, C++ supports references:
int score = 100;int& ref = score; ref = 200;cout << score; // 200Both score and ref refer to the same integer, so changing one changes the underlying value.
Pointer vs Reference
Pointers and references are related, but they are not the same thing.
| Pointer | Reference |
|---|---|
| Stores an address | Acts as an alias to existing data |
| Can usually be changed to point elsewhere | Usually remains bound to the same object |
| Can represent "points to nothing" | Typically must refer to an existing object |
| Can be dereferenced explicitly | Used like the original variable |
| Supports pointer arithmetic in languages such as C++ | Does not support pointer arithmetic |
| More explicit and flexible | Simpler for many use cases |
For example, a pointer can be redirected:
int a = 10;int b = 20; int* p = &a;p = &b; // p now points to bA reference such as int& ref = a; stays bound to a.
The important mental model is:
Pointer→ "Here is the address." Reference→ "Use this existing value by another name."Null: When Nothing Is Being Referenced
Sometimes a pointer does not currently point to a valid object.
int* p = nullptr;A null pointer does not mean that the pointer contains a useful memory location containing zero. It means:
The pointer currently does not point to an object or valid value.
Trying to dereference it is an error, because there is no valid object to access.
Different languages use different representations:
| Language | Represents nothing as |
|---|---|
| C / C++ | nullptr or NULL |
| Java | null |
| Python | None |
| JavaScript | null or undefined |
The exact behavior differs, but the underlying idea is similar: there is no usable object or value being referenced.
Pointers and the Heap
Now connect this to the previous chapter.
int* p = new int(100);Stack Heap p┌─────────┐│ 0x2000 │└────┬────┘ │ ↓ ┌─────────┐ │ 100 │ └─────────┘The pointer variable p is associated with the current execution context. The dynamically allocated integer exists in the heap. The pointer provides a way to reach that heap memory.
When the memory is no longer needed, delete p; releases it. Modern languages often handle this differently: Java uses garbage collection rather than requiring the programmer to call delete.
Why Pointers Matter in Data Structures
Now we reach the most important connection to DSA. Consider a linked list:
┌──────────────┐│ 10 │ next ───┼──────┐└──────────────┘ │ ↓ ┌──────────────┐ │ 20 │ next ───┼──────┐ └──────────────┘ │ ↓ ┌──────────────┐ │ 30 │ null │ └──────────────┘Each node contains a value plus a reference or pointer to another node.
The nodes do not need to sit next to each other in memory. The links connect them. This is the fundamental idea behind linked structures.
References in Trees
The same idea appears in trees. A node may contain references to its children:
[10] / \ ↓ ↓ [5] [20]The node does not need to physically contain the entire subtree. It only needs a way to reach the child nodes.
This is one reason pointers and references are so important in DSA.
References in Graphs
Graphs take the idea even further. A graph can contain many connections:
A / \ B C \ / D A → B, CB → A, DC → A, DD → B, CEach connection can be represented using references, pointers, or indexes depending on the implementation.
The important idea is:
References allow one piece of data to connect to another.
That connection is the foundation of linked lists, trees, graphs, and many other structures.
Passing Data to Functions
Pointers and references also matter when calling functions.
void increment(int x) { x++;} int value = 10;increment(value); // value is still 10This does not modify the original value in C++ because x receives a copy. Changing x changes only the copy.
But a reference can allow the function to work with the original value:
void increment(int& x) { x++;} int value = 10;increment(value); // value is now 11There is no separate integer being modified. Both names refer to the same value.
A Note About "Pass by Reference"
You will often hear: "this language passes objects by reference."
Be careful with this statement. Different languages use different parameter-passing models, and terminology is often used loosely.
For example, Java uses pass-by-value. When an object is passed, the value being copied is the reference to that object.
Original reference ↓ [Object] ↑ │Copied referenceBoth references can reach the same object, but the reference itself was passed by value.
This distinction becomes important when you start comparing languages.
Common Pointer Mistakes
Watch out
Dereferencing a null pointer. There is no valid object to access.
int* p = nullptr;cout << *p; // no valid objectUsing an invalid pointer. A pointer can become invalid if the memory it points to has already been released. The pointer still contains an address, but that memory is no longer valid for the original object.
int* p = new int(10);delete p; cout << *p; // invalidMemory leaks. If dynamically allocated memory is never released when required, the program can continue consuming memory unnecessarily. This is called a memory leak.
Confusing a pointer with the value. Given int* p = &score;, then p is an address and *p is a value. They are not the same thing.
Do You Need Pointers in Every Language?
No. Languages expose memory differently.
C / C++ make pointers explicit and powerful. You can directly work with memory addresses.
Java does not expose raw pointers. Object references are used instead:
Student s = new Student();You can think of s as a reference to the object, but you cannot directly manipulate its memory address like you can in C++.
Python also hides raw memory addresses behind object references, and handles the underlying memory management for you.
This gives you an important distinction:
Pointer→ explicit memory-address concept Reference→ language-level way to access another object/valueThe exact implementation differs between languages.
Quick Check
- What is a memory address?
- What does a pointer store?
- What is dereferencing?
- What is the difference between
pand*pin C++? - What is a reference?
- How is a pointer different from a reference?
- What does
nullptrmean? - Why are pointers and references important for linked lists?
- How are child nodes connected in a tree?
- Does Java use raw pointers like C++?
Quick Recap
- A memory address identifies where data is stored.
- A pointer stores a memory address.
- Dereferencing accesses the value at the address stored by a pointer.
- A pointer can be used to access or modify the data it points to.
- A reference provides another way to refer to existing data.
- Pointers can generally be redirected to another location; references are typically bound to an existing object.
- A null pointer or reference represents the absence of a usable object or value.
- Dynamically allocated data can be accessed through pointers or references.
- Linked lists, trees, and graphs rely heavily on connections between objects.
- Languages expose pointers and references differently.
Where This Leads
You now have the complete memory foundation:
Memory ↓How data is stored ↓Stack & Heap ↓Where data lives ↓Pointers & References ↓How data can connectNow we can finally start using these ideas to understand Data Structures.
The first major structure is one you have already seen several times: Arrays. An array takes values and organizes them into a structure that allows efficient indexed access.
From there, we will gradually move from arrays to linked lists, stacks and queues, trees, and graphs.
Key takeaway
Pointers and references provide ways to reach existing data indirectly. A pointer explicitly stores an address, while a reference provides a language-level way to refer to existing data. These concepts form the foundation for understanding linked lists, trees, graphs, and many dynamic data structures.