Previous chapter: Chapter 6: Arrays and the C++ String Class
This chapter introduces one of C++'s most powerful and critical features: pointers. Pointers allow you to interact directly with memory addresses, enabling advanced data structures, high-performance code, and manual memory management.
1. Pointers: Variables that Store Addresses
A pointer is a variable that stores the memory address of another variable. By storing the address, a pointer gives you indirect access to the data stored at that location.
Declaring a Pointer
You declare a pointer by placing an asterisk (*) between the data type and the variable name.
int number = 42;
int* ptr; // Declaration of a pointer to an integer
// Initialization: Store the address of 'number' in 'ptr'
ptr = &number;
The Address-of Operator (&)
The address-of operator (&) is a unary operator used to retrieve the memory address of a variable.
The Dereference Operator (*)
The dereference operator (*), when used with a pointer, accesses the value stored at the memory address the pointer holds.
int value = 100;
int* p = &value; // p holds the address of value
std::cout << "Address of value: " << &value << std::endl; // The address
std::cout << "Value stored in p: " << *p << std::endl; // The content (100)
*p = 200; // Changes the value at the address p points to
std::cout << "New value: " << value << std::endl; // Output: 200
2. Pointers and Arrays
In C++, an array name is essentially a constant pointer to the first element of the array.
int arr[4] = {10, 20, 30, 40};
int* p_arr = arr; // arr decay to point to arr[0]
// Accessing the second element (20) using pointer arithmetic
std::cout << *(p_arr + 1) << std::endl; // Output: 20
Pointer arithmetic allows you to move the pointer forward or backward through sequential memory locations by increments equal to the size of the data type it points to.
3. Dynamic Memory Allocation
The memory introduced in Chapter 2 is typically allocated on the Stack (for local variables) and is automatically managed. However, C++ allows you to manually allocate memory on the Heap (or Free Store) for large or long-lived data structures using the new and delete operators.
Using new and delete
// Allocate an integer on the heap
int* dynamic_int = new int;
*dynamic_int = 50;
std::cout << "Dynamic value: " << *dynamic_int << std::endl;
// Release the memory back to the system
delete dynamic_int;
dynamic_int = nullptr; // Best practice: Set pointer to null after deletion
Avoiding Memory Leaks
Failing to call delete on memory allocated with new results in a memory leak, where the program loses the address of the allocated block, making it permanently inaccessible until the program terminates. This is why manual memory management is a complex responsibility in C++.