Pointers vs References vs Values
The Three Ways to Pass Data
void byValue(int x); // copies the value
void byPointer(int* p); // passes the address
void byReference(int& r); // passes an aliasComparison Table
| Dimension | Value | Pointer | Reference |
|---|---|---|---|
| Copy cost | Full copy | None | None |
| Null safety | Always valid | Can be nullptr | Never null |
| Reassignment | N/A | Can point elsewhere | Bound at initialization |
| Syntax | f(x) | f(&x) | f(x) |
| Access | x | *p | r |
When to Use Each
| Use | Method |
|---|---|
| Small types (int, char, pointers) | Value — copy is cheaper than indirection |
| Large types you don't modify | Const reference (const T&) — avoids copy, guarantees no mutation |
| Large types you modify | Reference (T&) — avoids copy, modifications propagate |
| Nullable parameter | Pointer (T*) — pass nullptr when absent |
| Optional parameter | Pointer (T*) — default to nullptr |
Follow-up Questions
Can a reference be null?
No. A reference must be initialized when declared and cannot be reassigned. However, a reference to a null pointer is undefined behavior:
int* p = nullptr;
int& r = *p; // undefined behavior — dereferencing nullptrWhen should you avoid passing by reference?
Avoid it for small primitive types (int, char, double) — copying them is cheaper than following a pointer. Also avoid non-const references when the function doesn't need to modify the argument — prefer const T& for read-only large objects.