Background:
Pointers are one of the core tools in C++ since the language's inception, essential for memory management and dynamic structures, as well as interaction with low-level system libraries. References were added later (with the advent of C++) to simplify syntax and enhance code safety.
Problem:
Memory management errors are among the most common issues in C++, especially with improper pointer usage (dangling pointers, memory leaks). Often, beginners do not understand when to use a reference as opposed to a pointer, or mistakenly believe they are completely interchangeable.
Solution:
A pointer (T*) is a variable that holds the address of an object, it can be nullptr, supports arithmetic, allows dynamic allocation and deallocation, and can be redirected to point to different objects.
A reference (T&) is an alias for another existing object. References must be initialized upon creation, cannot be "null" (referencing null), do not support arithmetic, but are more convenient and safer (for example, when passed to functions).
Code Example:
void increment_pointer(int* p) { if(p) ++(*p); } void increment_reference(int& r) { ++r; } int main() { int a = 5; increment_pointer(&a); increment_reference(a); }
Key Features:
Can a reference be changed after its initialization to refer to a different object?
No. A reference in C++ is a constant alias. After initialization, a reference always points to the same object, unlike a pointer, which can be redirected.
Code Example:
int a = 1; int b = 2; int& ref = a; // ref = b - assigns b's value, but ref continues to refer to a
Can a "null" reference or a reference to nullptr be created?
No, the standard does not allow references to nonexistent objects. This leads to undefined behavior.
Example:
int* p = nullptr; // int& r = *p; - UB
What is the difference between int const ptr and const int ptr?**
int* const ptr is a constant pointer to int (the pointer cannot be redirected, but the value can be changed). const int* ptr is a pointer to a constant int (the content it points to cannot be changed, but the pointer can be redirected).
Code Example:
int a = 1, b = 2; const int* ptr1 = &a; // *ptr1 cannot be changed, ptr1 = &b - is allowed int* const ptr2 = &a; // *ptr2 can be changed, ptr2 = &b - is not allowed
A junior developer used pointers for parameter passing, failed to check them for nullptr, resulting in crashes on errors.
Pros:
Cons:
An experienced developer used int& when passing is guaranteed, and int* when a nullptr is possible, always checking for null pointers.
Pros:
Cons: