C++ Reference vs Pointer
In this page:
Syntax Differences
Pointers use an asterisk (*) for declaration and dereferencing and an ampersand (&) to retrieve a variable's address, while references use only the ampersand at declaration and then behave exactly like a normal variable, with no special dereference syntax needed afterward.
Example: Syntax Differences
#include <iostream>
int main() {
int value = 5;
int *ptr = &value;
int &ref = value;
std::cout << *ptr << " " << ref << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Nullability
Pointers can be assigned nullptr to represent an empty or not-yet-initialized state, which is essential for optional or lazily-set data. References cannot be null — they must be bound to a valid variable the moment they're created, which rules out an entire category of null-pointer bugs.
Example: Nullability
#include <iostream>
int main() {
int *ptr = nullptr; // valid: represents "no value"
int value = 5;
int &ref = value; // references must always refer to something
std::cout << ref << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Reassignment
Pointers can be reassigned to point to a different variable at any time during their lifetime, making them suitable for iteration and dynamic data structures. References are bound to their target at initialization and can never be redirected to refer to anything else afterward.
Example: Reassignment
#include <iostream>
int main() {
int a = 1, b = 2;
int *ptr = &a;
ptr = &b; // pointers can be reassigned
std::cout << *ptr << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Pass-by-Value vs Reference vs Pointer
Pass-by-value copies the argument entirely, which is safe but can be expensive for large objects. Pass-by-pointer copies just the memory address but requires the function to check for nullptr. Pass-by-reference shares the original variable directly with clean syntax and no null-check burden.
Example: Pass-by-Value vs Reference vs Pointer
#include <iostream>
void byValue(int x) { x = 100; }
void byReference(int &x) { x = 100; }
void byPointer(int *x) { *x = 100; }
int main() {
int a = 1, b = 1, c = 1;
byValue(a);
byReference(b);
byPointer(&c);
std::cout << a << " " << b << " " << c << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Use Cases
Use references by default for clean function parameters and for operator overloading, where the syntax reads naturally. Reach for pointers instead when you need to represent an optional/absent value with nullptr, perform pointer arithmetic, or manage memory you allocated on the heap yourself.
Example: Use Cases
#include <iostream>
void printValue(const int &x) { // reference: clean parameter syntax
std::cout << x << std::endl;
}
int main() {
int arr[] = {1, 2, 3};
int *ptr = arr; // pointer: needed for array iteration
printValue(*ptr);
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 11 topics to unlock
0/11 topics done
Complete these topics first: