Pointers are variables that store memory addresses rather than values. If a regular variable is a house, a pointer is the address written on an envelope — it tells you where to find the house, but it isn't the house itself.

Memory addresses

Every variable in your program occupies a location in memory. That location has an address — a number that identifies exactly where in RAM the value is stored. In C++, you can get that address with the & operator:

int score = 42;
cout << &score; // prints something like 0x7ffd5e2a1234

Declaring a pointer

A pointer is declared with a * after the type:

int* ptr;       // ptr is a pointer to an int
ptr = &score;   // ptr now holds the address of score

Dereferencing

To access the value at the address a pointer holds, use * again (this is called dereferencing):

cout << *ptr;   // prints 42 (the value at that address)
*ptr = 100;     // changes score to 100 through the pointer
cout << score;  // prints 100

When to use pointers

  • When you need to pass large objects to functions without copying them
  • When you need a function to modify its arguments
  • When working with arrays (arrays are fundamentally pointer-based)
  • When managing dynamic memory with new and delete

Null pointers

Always initialise pointers. An uninitialised pointer points to a random memory location and dereferencing it is undefined behaviour. Use nullptr:

int* ptr = nullptr;
if (ptr != nullptr) {
    cout << *ptr;
}

Common mistakes

  • Dereferencing a null or uninitialised pointer (crashes your program)
  • Forgetting to delete dynamically allocated memory (memory leak)
  • Returning a pointer to a local variable (the variable goes out of scope)

In modern C++, prefer references over raw pointers where possible, and use smart pointers (unique_ptr, shared_ptr) for dynamic memory. Raw pointers are still important to understand, but they're used less in production code than they were in older C++.