Pointers and References¶
Understanding how computer memory is structured and how variables access it is what gives C++ its low-level efficiency and control. While higher-level languages hide memory addresses, C++ gives you direct control over them through pointers and references.
1. Computer Memory and Pointers¶
Every variable you declare is stored in the computer's Random Access Memory (RAM). Each byte of RAM has a unique number assigned to it, which is its memory address.
A pointer is a variable that stores a memory address as its value, rather than a standard data type.
Pointer Declaration and Direct Access Operators¶
To work with pointers, C++ provides two primary operators:
- & (Address-of Operator): Retrieves the memory address of a variable.
- * (Dereference/Indirection Operator): Accesses the data stored at the memory address contained within a pointer.
Pointer Sizes¶
Because pointers store memory addresses, their size depends strictly on the CPU architecture of your system, not the data type they point to: - On 32-bit operating systems (e.g., legacy Raspberry Pi OS), all pointers are 4 bytes. - On 64-bit operating systems (e.g., modern Raspberry Pi OS running ARM64), all pointers are 8 bytes.
2. Safe Pointer Initialization: nullptr¶
Uninitialized pointers contain garbage addresses. Attempting to dereference an uninitialized pointer leads to Undefined Behavior (UB), typically causing a segmentation fault (crash) or memory corruption.
Always initialize your pointers. If you do not have a valid address immediately, initialize the pointer to nullptr.
Why nullptr is Better than NULL or 0¶
In old C and C++98, NULL or 0 was used to represent a null pointer. However, NULL is simply a macro for the integer 0. This caused type-safety problems and function overloading issues:
3. Pointers and Constants: The const Matrix¶
Combining pointers with the const keyword restricts modification. The placement of the const keyword determines what is immutable:
1. Pointer to Constant Data (const T*)¶
The data pointed to cannot be modified through this pointer, but the pointer itself can point to a different address.
2. Constant Pointer (T* const)¶
The pointer itself is constant and cannot point to another address, but the data it points to can be modified.
3. Constant Pointer to Constant Data (const T* const)¶
Neither the pointer nor the data can be modified.
Memory Aid: Read pointer declarations from right to left:
- int* const ptr $\rightarrow$ ptr is a const pointer to an int.
- const int* ptr $\rightarrow$ ptr is a pointer to an int which is const.
4. References¶
A reference is an alias (another name) for an existing variable. It behaves like a constant pointer that is automatically dereferenced by the compiler.
Essential Rules of References¶
- Must be Initialized: You cannot declare a reference without binding it to an object.
- Cannot be Rebound: Once a reference is created, it cannot be changed to refer to another variable. Any assignment to the reference changes the value of the underlying variable.
- Cannot be Null: A reference must always refer to a valid object in memory.
5. Pointers vs. References: Feature Matrix¶
| Feature | Pointer (T*) |
Reference (T&) |
|---|---|---|
| Nullability | Can be nullptr |
Must refer to a valid object |
| Reassignable | Yes (can point to a different variable) | No (bound to the initial variable for life) |
| Initialization | Optional (but highly recommended) | Mandatory at declaration |
| Syntax | Explicit dereference using * and -> |
Direct access (behaves like a standard variable) |
| Arithmetic | Supported (ptr++, ptr + 5) |
Not supported |
| Size | 4 or 8 bytes (stores address) | Typically compiler-optimized out (shares object size) |
6. Pointer Arithmetic and Arrays¶
Arrays in C++ are stored as contiguous blocks of memory. When you pass an array to a function, it decays into a pointer pointing to its first element.
Related Guides¶
- Memory Management — Dynamic memory allocation, Stack vs Heap, and smart pointers.
- Classes and Objects — Passing objects via reference and pointers.