logo
A Beginner's Guide to Pointers in C++
Demystifying pointers in C++, explaining memory addresses, the dereference operator, and common use cases like dynamic memory.

Pointers are one of the most powerful, and often most feared, features in C++. They allow you to interact directly with memory, leading to highly efficient code but also presenting new challenges. Understanding them is a rite of passage for any serious C++ programmer.

What is a Pointer?

Think of your computer's memory as a giant street of numbered houses. Each house has a unique address. A variable, like int my_age = 25;, is like putting the number 25 inside the house at a specific address, say, address 1001.

A pointer is not the house itself, nor is it the value inside. A pointer is a special variable that stores the address of another variable. It "points to" where the data lives.

Declaring and Using Pointers

You use two special operators when working with pointers:

  • The "address-of" operator (&): This gets the memory address of a variable.
  • The "dereference" operator (*): This gets the value that a pointer is pointing to.

Let's see it in action:

#include <iostream>

int main() {
    int my_age = 25; // A regular integer variable

    // Declare a pointer.
    // 'int*' means this pointer is intended to store the address of an integer.
    int* age_ptr;

    // Assign the address of 'my_age' to the pointer.
    age_ptr = &my_age;

    // Print the memory address stored in the pointer
    std::cout << "Address stored in age_ptr: " << age_ptr << std::endl;

    // Print the value at the address the pointer is pointing to.
    // This is called "dereferencing" the pointer.
    std::cout << "Value at that address: " << *age_ptr << std::endl; // Prints 25

    // You can also change the original variable's value through the pointer.
    *age_ptr = 30;
    std::cout << "The value of my_age is now: " << my_age << std::endl; // Prints 30

    return 0;
}

Why Use Pointers?

If you can just use the variable directly, why bother with pointers?

1. Dynamic Memory Allocation: Sometimes you don't know how much memory you'll need until your program is running. Pointers are essential for allocating memory on the heap, a large pool of memory available to the program.

// 'new int' allocates enough memory for one integer on the heap
// and returns a pointer to that memory location.
int* dynamic_int_ptr = new int;

*dynamic_int_ptr = 100; // Store 100 in our new memory location.

// IMPORTANT: When you are done with memory you allocated on the heap,
// you MUST release it to prevent memory leaks.
delete dynamic_int_ptr;

This is fundamental for creating data structures like linked lists and trees that can grow and shrink in size.

2. Passing Large Objects to Functions: When you pass a large object (like a complex class or struct) to a function, C++ by default creates a copy of it. This is slow and uses a lot of memory. By passing a pointer to the object instead, you are only passing its memory address, which is extremely fast and efficient.

void print_large_object(LargeObject* obj_ptr) {
    // Access members of the object using the arrow operator (->)
    std::cout << obj_ptr->get_name() << std::endl;
}

int main() {
    LargeObject my_large_object;
    // We pass the address, avoiding a costly copy.
    print_large_object(&my_large_object);
}

Pointers are a deep topic with more advanced uses, but mastering these fundamentals—the address-of (&) and dereference (*) operators and their role in dynamic memory—is a critical step. For more examples, try asking our Question Solver to explain pointer-based code.