Search⌘ K
AI Features

Managing Dynamic Memory

Explore how dynamic memory works in C++ beyond stack allocation, including manual use of new and delete, and the safer management of heap memory using smart pointers such as std::unique_ptr and std::shared_ptr. Understand ownership concepts, lifecycle, and how to prevent common issues like memory leaks, dangling pointers, and double frees. This lesson equips you to manage memory effectively in real-world C++ applications.

The variables we have used so far live on the stack. The stack is fast and managed automatically, but it has strict limitations: variables must have a known size at compile time, and they vanish the moment their function ends. Real-world applications, however, often need data to survive across function calls or grow dynamically based on user input.

To handle this, C++ provides the heap (also called the free store). The heap offers immense flexibility, but it comes with a catch: unlike the stack, the heap does not clean up after itself. If we take memory, we must give it back, or our program will eventually crash. In this lesson, we will learn how to wield this power responsibly using modern tools that automate the cleanup for us.

Manual allocation with new and delete

When we need memory that persists beyond the current scope, we use the new operator. This operator dynamically allocates memory from the free store (commonly backed by the heap) and returns a pointer to that memory.

Because this memory is not on the stack, it is not reclaimed when the function returns. We must explicitly release it using the delete operator.

  • new T: Allocates a single object of type T and returns T*.

  • delete ptr: Destroys the object and frees the memory.

  • new T[n]: Allocates an array of n objects ...

C++ 23
#include <iostream>
int main() {
// 1. Allocate a single integer on the heap
int* numPtr = new int(42);
std::cout << "Value: " << *numPtr << "\n";
// 2. Allocate an array of 5 integers
int* arrPtr = new int[5]{1, 2, 3, 4, 5};
std::cout << "Array element 2: " << arrPtr[2] << "\n";
// 3. Clean up manual memory
delete numPtr; // Deletes single object
delete[] arrPtr; // Deletes array
// Pointers now hold invalid addresses (dangling pointers).
// It is good practice to set them to nullptr immediately if they persist.
numPtr = nullptr;
arrPtr = nullptr;
return 0;
}

Let’s understand this step by step: ...