Skip to content

Beginner · References, pointers, arrays and strings · topic 10 of 42 · 35 min

Pointers, the stack and the heap

Explanation

A pointer is a variable that stores a memory address. & gives the address of a variable and * goes to the value at an address. nullptr means "points to nothing". Memory you get with new must be freed with delete, which is error-prone, so modern C++ uses containers and smart pointers instead.

Memory and addresses

Your computer's memory is a long row of numbered bytes. The number of a byte is its address. Every variable lives at some address. A pointer is a variable whose value is an address: it "points to" another variable.

Think of it like this: Your house is a variable; your postal address is a pointer. You can write the address on a card and give it to a courier. The courier (the program) can follow the address to deliver a parcel (change the value). A blank card that points nowhere is nullptr.
cpp
int seats = 72;
int* p = &seats;        // p holds the address of seats

std::cout << p << '\n';     // an address like 0x7ffd5e8c (changes each run)
std::cout << *p << '\n';    // 72: the value at that address
*p = 60;                    // change seats through the pointer
std::cout << seats << '\n'; // 60
int* means "pointer to int". &seats is the address of seats. *p dereferences: it goes to the address and uses the value there.
SymbolIn a declarationIn an expression
*int* p; (p is a pointer)*p (the value p points to)
&int& r = x; (r is a reference)&x (the address of x)

nullptr and checking before use

cpp
int* p = nullptr;      // points to nothing
if (p != nullptr) {
    std::cout << *p;
}
// *p here would be undefined behaviour, usually a crash ("Segmentation fault")
Always initialise pointers, and check for nullptr when a pointer may be empty.

References versus pointers

ReferencePointer
Can be empty?No, always bound to a variableYes, nullptr
Can change what it refers to?NoYes, p = &other;
Syntax to use the valuejust the name*p (or p->member for objects)
Typical usefunction parameters, aliasesoptional links, arrays, low-level code, C libraries

Rule of thumb: use a reference when something must always exist; use a pointer when "nothing" is a valid answer, or when you need to point at different things over time.

The stack and the heap

Local variables live on the stack: memory that is set up automatically when a function starts and cleaned up when it ends. It is fast but limited in size. The heap (also called the free store) is a big pool of memory you request while the program runs, for data whose size you only know at run time or that must outlive the function that made it.

cpp
int* marks = new int[5]{70, 80, 90, 60, 85};   // ask the heap for 5 ints
std::cout << marks[2] << '\n';                 // 90
delete[] marks;                                // give it back (new[] needs delete[])

int* one = new int(42);
delete one;                                    // new needs delete
new gets heap memory and returns a pointer to it. You must delete it exactly once.
Careful: Manual new/delete causes the worst C++ bugs: forgetting delete leaks memory; deleting twice ("double free") or using memory after delete ("use after free") crashes or corrupts data, and are common security holes. Modern C++ almost never uses raw new/delete in normal code. Use std::vector for lists and std::unique_ptr / std::make_unique for single objects; you will learn these in the smart pointers module.

Pointer arithmetic, briefly

cpp
int a[3] = {10, 20, 30};
int* p = a;            // an array name turns into a pointer to its first item
std::cout << *(p + 1); // 20, same as a[1]
p + 1 moves by one int, not one byte. a[i] is defined as *(a + i).

Common mistakes

  • Declaring int* a, b; thinking both are pointers. Only a is; b is a plain int. Declare one per line.
  • Using an uninitialised pointer (int* p; *p = 5;): it points at a random place.
  • Returning the address of a local variable: it dies when the function returns (a dangling pointer).
  • Mixing new[] with delete (without []), which is undefined behaviour.
Tip: Compile with -fsanitize=address -g while practising pointers (GCC and Clang). AddressSanitizer stops the program at the exact line of a use-after-free or out-of-bounds access and explains it.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Pointers, the stack and the heap · 1/6

Pointers

Pointers are the part of C plus plus that scares people. Take it slowly: a pointer is just a variable that holds an address.

Prefer a video by a teacher? Find free videos on “c++ pointers explained address dereference nullptr new delete beginners” on YouTube ↗

In real life: Linked train coaches

A train is a chain of coaches, each coupled to the next. Programs store chains like this as a linked list: each node holds its data and a pointer to the next node, and the last node points to nullptr. Walking the chain means following pointers until you reach nullptr. (In real code, std::list or std::vector usually does this for you.)

cpp
#include <iostream>
#include <string>

struct Coach {
    std::string name;
    Coach* next;
};

int main() {
    Coach c3{"S2", nullptr};
    Coach c2{"S1", &c3};
    Coach c1{"Engine", &c2};
    for (Coach* p = &c1; p != nullptr; p = p->next) {
        std::cout << p->name << ' ';
    }
    // prints: Engine S1 S2
}
p->name is short for (*p).name. The loop stops at nullptr. These coaches live on the stack, so there is nothing to delete.

Practice (0/4 done)

Task 1 · Question

int x = 7; int* p = &x; What is *p?

Task 2 · Question

What does this print? int a = 1, b = 2; int* p = &a; *p = 10; p = &b; *p = 20; std::cout << a << " " << b;

Task 3 · Question

Which line has a bug? 1: int* data = new int[100]; 2: data[0] = 5; 3: delete data;

Task 4 · Practice

Write int* findFirst(int* arr, int size, int target) that returns a pointer to the first element equal to target, or nullptr if it is not there. In main, use it to find a value and change it through the returned pointer; handle the not-found case.

Quick quiz

Question 1

1.What does int* p = nullptr; mean?

Question 2

2.In int* a, b; what is b?

Question 3

3.Which memory is cleaned up automatically when a function returns?

Question 4

4.What is a memory leak?

Question 5

5.For a struct pointer s, what is s->name the same as?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What does int* p = nullptr; mean?

Answer: p points to nothing

nullptr is the null pointer value: an address that refers to no object.

In int* a, b; what is b?

Answer: An int

The * belongs to a only. Declare pointers one per line to avoid this trap.

Which memory is cleaned up automatically when a function returns?

Answer: The function's local variables on the stack

Stack variables are destroyed at the end of their scope; heap memory stays until deleted.

What is a memory leak?

Answer: Heap memory that is never freed after it is no longer needed

Leaked memory stays reserved until the program ends; long-running servers slowly run out.

For a struct pointer s, what is s->name the same as?

Answer: (*s).name

The arrow operator dereferences the pointer and then picks the member.

How does Rust decide when to free heap memory?Related

Answer: Ownership rules let the compiler insert the free at the right point

Rust frees a value when its owner goes out of scope, decided at compile time.

From Memory 101: the stack and the heap

What is the zero value of a pointer?Related

Answer: nil

An unset pointer is nil.

From Pointers without fear

Who frees heap memory in C?Related

Answer: The program, by calling free

There is no garbage collector.

From Stack and heap

How should a pointer be printed with printf?Related

Answer: %p with a (void *) cast

%p expects a void pointer.

From Addresses and pointers

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 2 more topics in “References, pointers, arrays and strings” before its exam: Arrays, std::array and a first look at std::vector, Text: C strings and std::string.
  2. Module 3 exam: References, pointers, arrays and strings · 12 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Classes, constructors and RAII. 42 topics left in the course before the final exam.

← Previous: References: another name for a variable