Pointers
2 min read
Pointers
A pointer holds the memory address of another variable. Pointers are central to C++ — they underpin arrays, dynamic allocation, polymorphism, and data structures. They are also a common source of bugs. Modern C++ reduces direct pointer use through smart pointers and references, but understanding raw pointers is still essential.
Declaring and using pointers
#include <iostream>
int main() {
int x = 42;
int* p = &x; // p holds the address of x
std::cout << x << "\n"; // 42 — the value
std::cout << p << "\n"; // 0x... — the address
std::cout << *p << "\n"; // 42 — dereference: value at address
*p = 100; // modify x through p
std::cout << x << "\n"; // 100
}
&x is the address-of operator. *p is the dereference operator — it reads or writes the value at the address stored in p.
nullptr
Use nullptr for a pointer that points to nothing:
int* p = nullptr;
if (p != nullptr) {
std::cout << *p << "\n";
} else {
std::cout << "null pointer\n";
}
Dereferencing nullptr is undefined behavior — it typically crashes the program. Always check before dereferencing a pointer that might be null.
Pointer arithmetic
Adding an integer to a pointer advances it by that many elements (not bytes):
#include <iostream>
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int* p = arr; // points to arr[0]
std::cout << *p << "\n"; // 10
std::cout << *(p+1) << "\n"; // 20
std::cout << *(p+4) << "\n"; // 50
p++;
std::cout << *p << "\n"; // 20
}
Array indexing arr[i] is exactly *(arr + i).
Pointers to pointers
int x = 5;
int* p = &x;
int** pp = &p; // pointer to pointer
std::cout << **pp << "\n"; // 5
Double pointers appear in C APIs that need to return a pointer through a parameter.
const and pointers
const can apply to the pointer, the pointed-to value, or both:
int x = 10, y = 20;
const int* p1 = &x; // pointer to const int: cannot modify *p1
p1 = &y; // can reassign the pointer itself
int* const p2 = &x; // const pointer to int: cannot reassign p2
*p2 = 99; // can modify the value
const int* const p3 = &x; // neither the pointer nor the value can change
The rule: read the declaration right-to-left. const int* — "pointer to const int."
void*
A void* pointer holds an address with no type information. It can point to anything but cannot be dereferenced without casting:
void* raw = malloc(64);
int* ip = static_cast<int*>(raw);
*ip = 42;
free(raw);
void* is common in C APIs but rare in modern C++. Smart pointers and templates eliminate most of its traditional uses.
Pointer vs. reference
| Feature | Pointer | Reference |
|---|---|---|
| Can be null | Yes | No |
| Can be reseated | Yes | No |
| Syntax at call site | f(&x) |
f(x) |
| Arithmetic | Yes | No |
Use references when the value is always present and you do not need to reseat; use pointers when null is a valid state or when you need dynamic dispatch over ownership.
Learn modern C++ through working code. Each chapter introduces one concept — variables, functions, classes, templates, smart pointers, concurrency — with a clear example, a line-by-line explanation, and notes on how it applies in real programs.
View book →