Pointers and references
โ Report an issue with this lessonint value = 42;
int* ptr = &value; // ptr holds the address of value
int& ref = value; // ref is an alias for value
*ptr = 10; // changes value through the pointer
ref = 20; // changes value through the reference
std::cout << value; // 20
A pointer can be reassigned to point elsewhere, or set to
nullptr. A reference is bound permanently to one variable at
creation and can never be null -- prefer references when you don't need
that flexibility, since they're harder to misuse.
Pointer arithmetic is one of the things that separates C++ from most
higher-level languages: incrementing a pointer moves it forward by
sizeof(T) bytes, not one byte, which is what makes it work
correctly with arrays of any element type:
int arr[] = {10, 20, 30};
int* p = arr; // arrays decay to a pointer to their first element
std::cout << *p; // 10
p++; // now points at arr[1], not arr[0] + 1 byte
std::cout << *p; // 20
std::cout << p[1]; // 30 -- p[i] is shorthand for *(p + i)
const interacts with pointers in two independent ways,
and it's worth being able to read the declaration precisely -- read it
right to left from the variable name:
const int* a; // pointer to const int: can't modify *a, but a can point elsewhere
int* const b = &x; // const pointer to int: can modify *b, but b can never repoint
const int* const c = &x; // both: neither *c nor c itself can change
A dangling pointer -- one that still holds an address whose object has already been destroyed -- is one of the most common sources of undefined behavior in C++. Returning the address of a local variable is the classic mistake:
int* danger() {
int local = 42;
return &local; // local's storage is gone the instant the function returns
} // calling code that dereferences the result reads garbage, or worse
The compiler will often warn about this specific case, but the same
bug shows up less obviously with pointers into containers that get
reallocated (a vector growing past its capacity
invalidates pointers/iterators into it) or with a unique_ptr
being deleted while a raw pointer obtained from .get() is
still in use elsewhere. When in doubt about whether a raw pointer might
be dangling, prefer a smart pointer or a reference with a clearly
bounded lifetime instead -- the next lesson covers exactly that.
A pointer can also point to a pointer (int**), which
shows up when a function needs to modify what a caller's pointer points
to, or in old-style C APIs (like argv-style string arrays,
char**). It's rare in idiomatic modern C++, but you'll
still encounter it reading lower-level or interop code.
Try it yourself
20
Run your code and get it working before marking this lesson complete.
9 more lessons โ including Project: build a thread-safe task queue โ and a final exam plus a certificate are waiting.
Unlock the full course โ $99.99