C, C++, MFC  

Chapter 7: Pointers and Memory Management in C++

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

  • new: Allocates memory on the heap and returns the address (a pointer) to that memory.

  • delete: Releases the memory allocated by new back to the system.

// 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++.