Learn › Linked lists

Pointers first (C++)

The memory model behind linked lists: addresses, dereferencing, nullptr, and ownership. · 9 min read

A linked list only makes sense once pointers make sense. In C++, a pointer is a variable whose value is a memory address. Instead of storing an object directly, it stores where that object lives.

The three pointer ideas

  • &x means address of x. It asks: where in memory is this variable?
  • int* p means p is a pointer to int. It can store the address of an int.
  • *p means dereference p. It asks: go to the address inside p and read/write the value there.

That overloaded * is annoying at first: in a declaration (int* p) it means pointer type; in an expression (*p) it means dereference.

int x = 42;
int* p = &x;      // p stores the address of x

cout << x;        // 42
cout << p;        // some address, e.g. 0x7ffee...
cout << *p;       // 42, the value at that address

*p = 99;          // write through the pointer
cout << x;        // 99

The arrow operator

When a pointer points to a struct or class, C++ gives you a shortcut. These two lines mean the same thing:

(*node).value = 10;
node->value = 10;

Use -> when you have a pointer to an object. Linked-list code is full of it because each node points to another node.

nullptr: pointing nowhere

nullptr means the pointer does not point to a valid object. In linked lists, the last node's next pointer is nullptr, meaning "there is no next node".

int* p = nullptr;

if (p != nullptr) {
    cout << *p;   // safe only if p points somewhere real
}

Dereferencing nullptr is a serious bug: the program is asking the CPU to read memory at no valid object.

Dynamic allocation

Linked-list nodes usually live on the heap because they must survive after the function that created them returns. In beginner DSA C++, you often see new to allocate and delete to release:

int* p = new int(7);  // allocate one int on the heap
cout << *p;          // 7

delete p;            // release the memory
p = nullptr;         // avoid a dangling pointer

Modern production C++ often prefers smart pointers (unique_ptr, shared_ptr) or containers, but raw pointers are still the clearest way to learn how linked lists work under the hood.

Pointer bugs to recognise

  • Null pointer: using p->next when p == nullptr.
  • Dangling pointer: using a pointer after delete freed the object.
  • Memory leak: losing the last pointer to heap memory without deleting it.
  • Lost list: moving head forward without saving the old node when you still need it.
  • Cycle by mistake: setting node->next to an earlier node unintentionally.

Previous: Backtracking · Next: Linked lists

More in Linked lists