References vs Pointers, and When to Use Each
Comparing C++'s two ways to indirectly access a variable, and choosing between them.
What you'll learn
- List the concrete differences between a reference and a pointer: nullability, reseatability, syntax
- Choose a reference parameter when a function needs to modify an argument that always exists
- Choose a pointer when 'no value' (nullptr) or reassignable indirection is a genuine requirement
Explanation
You've now seen both of C++'s indirection mechanisms: references (this course's variables lesson) and pointers (inherited from C, this course's earlier lessons covered their C form, which C++ keeps unchanged). Put side by side, three concrete differences matter most in practice. First, nullability: a pointer can be nullptr (pointing at nothing); a reference can never be null -- it's always bound to a real object from the moment it's declared. Second, reseatability: a pointer can be reassigned to point at a different object later; a reference is permanently bound to whatever it was initialized with. Third, syntax: using a reference looks exactly like using the underlying value directly (no * needed to read or write through it), while a pointer requires explicit * to dereference and & to obtain an address in the first place.
These differences translate into a practical rule of thumb for function parameters. Use a reference parameter (int &value) when the function needs to read or modify an argument that's guaranteed to exist -- the calling code is slightly cleaner too, since you pass the variable directly rather than writing &variable at the call site. Use a pointer parameter (int *value) when "no value" is a genuine, meaningful possibility (representing that with nullptr) or when the function needs to store the address for later, reseatable use, rather than for the duration of just this one call.
Neither is objectively "better" -- they solve different problems. Modern C++ style generally reaches for references first for ordinary in/out parameters, and reserves pointers for cases that specifically need nullability or reseating, rather than defaulting to pointers out of habit from C.
Guided lab
Fill in the blank: declaring a reference parameter
Fill in the missing symbol so this parameter is a reference, then predict the output.
#include <iostream>
void incrementByReference(int ____value) {
value++;
}
int main() {
int a = 5;
incrementByReference(a);
std::cout << "After increment: " << a << std::endl;
return 0;
}Stuck? Get a hint.
Common mistakes
- Using a pointer parameter where a reference would do, adding unnecessary null-checking and dereference syntax for a value that's guaranteed to exist.
- Trying to represent 'no value' with a reference -- references can never be null, so a pointer (or a type built specifically for optional values) is needed instead.
- Forgetting a reference must be initialized immediately and can never be reseated, unlike a pointer, and trying to use one as if it could be reassigned later.
Knowledge check
Takeaway
Reach for a reference parameter by default for a value guaranteed to exist; reach for a pointer specifically when nullability or reseatable indirection is a genuine requirement.
Summary
References can't be null or reseated and need no dereference syntax; pointers can be null and reassigned but need explicit * and &, making each better suited to different situations.
References
Your notes
Notes save automatically.
Finished this lesson?
Mark it complete to track your progress and schedule a future review.
AI tutor
The optional AI tutor isn't enabled in this deployment. All lessons, exercises, quizzes, and search work fully without it.