References vs Pointers
Key differences: nullability, rebinding, indirection costs, and memory semantics.
In C++, when working with data there are two important concepts: pointers and references. Both are used to “refer to” another variable; however, they differ in how they work, how they behave in memory, and in terms of safety. In this article we’ll look at pointers and references, their differences, and their use cases with examples.
1. What Is a Pointer?
A pointer is a special variable that holds a memory address. Pointers let you access the value of another variable indirectly.
#include <iostream>
using namespace std;
int main() {
int number = 10;
int *ptr = &number; // the address of 'number' is assigned to ptr
cout << "number value: " << number << endl;
cout << "ptr value (address): " << ptr << endl;
cout << "value pointed to by ptr: " << *ptr << endl;
*ptr = 20; // we changed the value through the pointer
cout << "new number value: " << number << endl;
return 0;
}
Here, *ptr (dereferencing) accesses the value of the variable the pointer points to.
Because a pointer can manipulate memory addresses directly, it’s very powerful — but risky if not used carefully.
2. What Is a Reference?
A reference is an “alias” for another variable. Unlike a pointer, it doesn’t store an address explicitly — it directly shares the same memory. It must be bound to a variable at the moment it is declared.
#include <iostream>
using namespace std;
int main() {
int x = 50;
int &ref = x; // ref is a reference to x
cout << "x: " << x << ", ref: " << ref << endl;
ref = 100; // changing x through the reference
cout << "new value of x: " << x << endl;
return 0;
}
In this example, ref actually shares the same memory location as x.
So when one changes, the other changes automatically.
3. Differences Between Pointers and References
The table below shows the main differences between the two:
| Feature | Pointer | Reference |
|---|---|---|
| Declaration | int *p = &x; |
int &r = x; |
| Holds an address? | Yes, it stores a memory address | No, it is directly bound to the variable |
| Can it be NULL? | Yes, it can be set to nullptr |
No, it must always refer to something |
| Can be rebound? | Yes, it can point to a different address | No, once bound it cannot be changed |
| Dereference | Access with *p |
Used directly |
| Memory management | Up to the programmer (new/delete) | Managed automatically |
| Performance | Indirect access | Direct access (usually cheaper) |
4. In-Memory View
Let’s see pointer vs reference behavior in memory:
int x = 10;
int *ptr = &x;
int &ref = x;
cout << "&x: " << &x << endl;
cout << "ptr: " << ptr << endl;
cout << "&ref: " << &ref << endl;
Example memory layout:
Variable | Address | Value
x | 0x61ff0c | 10
ptr | 0x61ff08 | 0x61ff0c
ref | 0x61ff0c | 10
As you can see, ref uses the same memory as x,
while ptr lives at its own address and stores another address (that of x).
5. Passing Pointers and References to Functions
You can pass pointers or references to functions to allow the function to modify external variables.
With a pointer
void Increment(int *p) {
(*p)++;
}
int main() {
int n = 5;
Increment(&n);
cout << n; // 6
}
With a reference
void Increment(int &r) {
r++;
}
int main() {
int n = 5;
Increment(n);
cout << n; // 6
}
Both approaches produce the same effect, but using a reference is cleaner and generally safer.
6. const References
If you don’t want the function to modify the value it receives by reference,
you can use the const keyword.
void Print(const string &text) {
cout << text << endl;
}
int main() {
string message = "C++ is great!";
Print(message);
}
const & references let you pass large objects to functions without copying them
while still preventing accidental modification — this is also good for performance.
7. Mixing Pointers and References
Sometimes pointers and references are used together. For example, you can have a reference to a pointer.
#include <iostream>
using namespace std;
int main() {
int x = 5;
int *p = &x;
int *&refToPointer = p; // reference to a pointer
*refToPointer = 10;
cout << x << endl; // 10
}
This looks a bit advanced, but it’s useful in situations involving dynamic memory or APIs that need to modify pointers.
8. Best Use Cases
- Pointers → dynamic memory (
new/delete), arrays, low-level tasks - References → function parameters, operator overloading, sharing objects
In modern C++, it’s often preferable to use references or
smart pointers (like std::unique_ptr) instead of raw pointers.
9. TL;DR
- A pointer stores an address; a reference is an alias for a variable.
- A pointer can be
nullptr; a reference cannot. - A pointer can be reassigned; a reference is bound once.
*paccesses the value a pointer points to; references are used directly.const &references pass large objects safely without copying.- Use pointers for memory management; use references for simpler, safer access.
- All examples can be run in Visual Studio 2022 or GCC 11+.