Pointers

A pointer holds the memory address of an object. Modern C++ needs raw pointers far less than C does — references, containers and smart pointers cover most jobs — but you still need to understand them: to read existing code, to express "optional reference", and to work with C libraries and low-level code.

Address and dereference

C++
#include <iostream>

int main() {
    int score = 42;
    int* p = &score;            // p holds the address of score

    std::cout << *p << '\n';    // * dereferences: the value at that address
    *p = 100;                   // change score through the pointer
    std::cout << score << '\n';
    std::cout << std::boolalpha << (p == &score) << '\n';
}
Output
42
100
true
SyntaxMeaning
int* pp is a pointer to int
&xThe address of x
*pThe object p points to
p->mMember m of the object p points to — same as (*p).m

Printing an address with std::cout << p shows a hexadecimal number that differs from run to run, so this course compares addresses rather than printing them.

nullptr

A pointer that points to nothing should be nullptr. Dereferencing a null pointer is undefined behaviour — usually a crash — so check before using a pointer that might be null:

C++
#include <iostream>
#include <string>
#include <vector>

struct User {
    std::string name;
    int age;
};

const User* find_user(const std::vector<User>& users, const std::string& name) {
    for (const auto& u : users) {
        if (u.name == name) return &u;
    }
    return nullptr;            // not found
}

int main() {
    std::vector<User> users{{"Ana", 31}, {"Ben", 27}};
    for (std::string name : {"Ben", "Zoe"}) {
        if (const User* u = find_user(users, name)) {
            std::cout << u->name << " is " << u->age << '\n';
        } else {
            std::cout << name << " not found\n";
        }
    }
}
Output
Ben is 27
Zoe not found

That's the main remaining use for raw pointers in modern C++: a non-owning, optional reference to an object that lives elsewhere. Never use NULL or 0 for pointers in C++ — nullptr has its own type and avoids overload confusion.

Pointers and const

C++
int main() {
    int a = 1, b = 2;
    const int* p1 = &a;     // pointer to const int: can't change *p1
    int* const p2 = &a;     // const pointer: can't change p2 itself
    p1 = &b;                // fine
    *p2 = 5;                // fine
    *p1 = 5;                // error
    p2 = &b;                // error
    return a + b;
}
Compiler error
main.cpp:7:9: error: read-only variable is not assignable
main.cpp:8:8: error: cannot assign to variable 'p2' with const-qualified type 'int *const'

Read right to left: const int* p is "a pointer to an int that is const"; int* const p is "a const pointer to an int".

Pointers and arrays

A C-style array converts to a pointer to its first element, and pointer arithmetic moves in whole elements. Modern code rarely does this by hand — std::span (lesson 19) wraps a pointer and a length safely:

C++
#include <iostream>

int main() {
    int primes[] = {2, 3, 5, 7, 11};
    int* p = primes;
    std::cout << *p << ' ' << *(p + 2) << ' ' << p[4] << '\n';
    for (int* it = primes; it != primes + 5; ++it) std::cout << *it << ' ';
    std::cout << '\n';
}
Output
2 5 11
2 3 5 7 11

Pointers vs. references

Use a reference when there is always an object and it won't change; use a pointer when "no object" is a valid state, or when you need to re-point. For optional values (not references), std::optional (lesson 43) is often clearer than a pointer.

Owning vs. non-owning

The most important question about any pointer is: who deletes the object? In modern C++ the answer is never "whoever holds a raw pointer". Objects are owned by containers, by local variables, or by smart pointers (lesson 29). A raw pointer only observes an object that someone else owns. Keeping to that rule eliminates most memory bugs.

Try it yourself

Write a function that returns a pointer to the cheapest product in a vector, or nullptr if the vector is empty.

Try it yourself · main.cpp
Edit the code, copy it into main.cpp, then compile and run it with c++ -std=c++20 -Wall main.cpp -o main && ./main. How to set up a C++ compiler
Output
cheapest: Eraser
empty shop