Dynamic Memory — new & delete
new and new[], why you must always pair a new with a matching delete, what a memory leak and a dangling pointer actually are, and why modern C++ often reaches for std::vector instead.
Stack vs Heap Memory
So far, every variable you've declared — int x;, int arr[5]; — has lived on the stack: a region of memory that's automatically managed. When a function ends, its stack variables are automatically cleaned up. Fast, simple, but limited in size and lifetime.
The heap is a much larger pool of memory that you control manually. Memory on the heap stays allocated until you explicitly free it — even after the function that created it has returned. This is what makes the heap useful for data that needs to outlive a single function call, or whose size isn't known until the program is running.
Allocating a Single Value with new / delete
The new operator allocates memory on the heap and returns a pointer to it. When you're done with that memory, you must free it with delete — the exact counterpart to new.
// heap_single.cpp #include <iostream> using namespace std; int main() { int* score = new int; // allocate one int on the heap *score = 95; cout << "Score: " << *score << endl; delete score; // free the memory — every new needs a matching delete score = nullptr; // avoid a dangling pointer return 0; }
new must be paired with exactly one matching delete. Not zero, not two — exactly one. Setting the pointer to nullptr right after deleting it is a defensive habit that stops you from accidentally using freed memory later.Allocating a Dynamic Array with new[] / delete[]
To allocate an array on the heap — one whose size can be decided while the program is running, not fixed at compile time — use new[]. It must be freed with delete[], using the square brackets to match.
// heap_array.cpp #include <iostream> using namespace std; int main() { int n = 5; int* arr = new int[n]; // allocate an array of 5 ints on the heap for (int i = 0; i < n; i++) { arr[i] = i * 10; } for (int i = 0; i < n; i++) { cout << arr[i] << " "; } cout << endl; delete[] arr; // must use delete[] for arrays allocated with new[] arr = nullptr; return 0; }
new, free with plain delete. If you allocate with new[], free with delete[]. Mismatching them is undefined behavior — the brackets aren't decoration, they tell the runtime exactly how the memory was structured.Memory Leaks — Why delete Matters
A memory leak happens when you allocate memory with new but never free it with delete. The memory stays reserved on the heap forever — even though your program has lost every pointer that could reach it — because nothing tells the operating system it's safe to reuse.
// leak_example.cpp — DON'T DO THIS, this function leaks memory #include <iostream> using namespace std; void leakyFunction() { int* data = new int[100]; // ... data is used here ... // BUG: missing "delete[] data;" — this memory is never freed } // data (the pointer) goes out of scope, the address is lost, the 100 ints leak forever int main() { leakyFunction(); // every call leaks another 100 ints worth of memory return 0; }
The fix is simple: always free what you allocate, in every code path — including any early return statements. A correct version of leakyFunction() would end with delete[] data; before its closing brace.
new with a delete is not optional discipline; it's a core requirement of writing correct C++.Dangling Pointers — The Bug to Avoid
A dangling pointer is a pointer that still holds the address of memory that has already been freed. Using it — reading it, writing to it, or even just checking it carelessly — is undefined behavior.
// dangling_pointer.cpp — DON'T DO THIS, the bug is using ptr after delete #include <iostream> using namespace std; int main() { int* ptr = new int(42); delete ptr; // memory is freed here // BUG: ptr still holds the OLD address — this is a dangling pointer cout << *ptr << endl; // undefined behavior — do NOT do this return 0; }
The fix, shown earlier in this lesson, is to set the pointer to nullptr immediately after deleting it: delete ptr; ptr = nullptr;. Dereferencing a nullptr still crashes your program — but it crashes predictably and immediately, which is far easier to debug than the silent corruption a dangling pointer can cause.
Looking Ahead: std::vector
Manually pairing every new with a delete is important to understand — but in modern C++, most day-to-day dynamic arrays are built with std::vector instead, which you'll meet later in this course's STL section.
std::vector allocates its own heap memory internally, grows automatically as you add elements, and frees that memory automatically when it goes out of scope — no manual new[] or delete[] required. Modern C++ style prefers it for most dynamic-array use cases. You're learning manual new/delete now because understanding what's happening underneath makes you a far stronger C++ programmer once you do start using std::vector.Lesson Summary
Let's recap everything you learned in this lesson:
new allocates a single heap value; free it with delete.new[] allocates a heap array; free it with delete[] — the brackets must match.delete causes a memory leak — memory reserved forever with no way back.std::vector, which manages heap memory automatically.new int[10];?Now it's your turn to write real code. Complete the challenge below in your own C++ environment.
Write a C++ program called
dynamic_sum.cpp that: declares a constant int n (for example, const int n = 6;), dynamically allocates an array of n integers with new[], fills it with values of your choice, computes and prints the sum of all elements, and then correctly frees the memory before the program ends.
Rules: Use
new int[n] to allocate — do not use a fixed-size stack array. Free it with delete[] exactly once, and only after you're done using it. Set the pointer to nullptr after deleting it.
💡 Show hints if you're stuck
- Allocate with
int* arr = new int[n]; - Fill it in a loop:
arr[i] = ...;for i from 0 to n-1 - Sum it in a second loop, adding
arr[i]to a running total - Finish with
delete[] arr; arr = nullptr;— the exact matching cleanup for new[]