C++: Dynamic Memory Allocation
Last updated: 2026-08-26
In previous lessons, variables and arrays were allocated on the stack — fixed in size, automatically freed when the function ends.
But if you need to store an uncertain amount of data (e.g., the user inputs 1000 integers, but you don't know at compile time), you need dynamic memory allocation — allocating memory on the heap.
1. Stack vs Heap
(1) 1.1 Two Memory Regions
| Comparison | Stack | Heap |
|---|---|---|
| Allocation timing | Determined at compile time | Determined at runtime |
| Size | Fixed (determined at compile time) | Variable (requested at runtime) |
| Deallocation timing | Automatic (when function ends) | Manual (using delete) |
| Efficiency | High | Low |
| Use cases | Local variables, arrays | Dynamically-sized data |
(2) 1.2 Everyday Analogy
| Real-life Analogy | Program Equivalent |
|---|---|
| Fast food restaurant (fixed menu, food served immediately after ordering) | Stack |
| Buffet (take as much as you want) | Heap |
2. new and delete
(1) 2.1 Allocating Memory with new
Syntax:
▶ Example 2: Dynamic Memory Management (Difficulty ⭐)
Type* pointerName = new Type;
Output:
(Program output)
Example:
#include <iostream>
int main() {
// Allocate an int on the heap
int* p = new int; // p Pointing to int on the heap
*p = 5; // Assign value to int on the heap
std::cout << "*p = " << *p << std::endl; // 5
return 0;
}
💡 Key point: new returns a pointer — pointing to the memory allocated on the heap.
(2) 2.2 Freeing Memory with delete
Syntax:
delete pointerName;
Example:
#include <iostream>
int main() {
int* p = new int;
*p = 5;
std::cout << "*p = " << *p << std::endl;
delete p; // ✅ Free heap memory
p = nullptr; // ✅ Good practice:Set to nullptr after freeing
return 0;
}
💡 Golden rule: new and delete must always come in pairs — every new needs a delete.
(3) 2.3 Forgetting delete Causes Memory Leaks
Error example:
#include <iostream>
void foo() {
int* p = new int;
*p = 5;
// ❌ Forgot to write delete p;
} // Function ends, p is destroyed, but int on heap is not freed (memory leak)
int main() {
for (int i = 0; i < 1000000; i++) {
foo(); // Each call leaks 4 bytes
}
// Program memory usage keeps growing, may eventually crash
return 0;
}
💡 Memory leak: Heap-allocated memory that is never freed and can no longer be accessed (because the pointer to it has been destroyed).
3. Dynamic Arrays
(1) 3.1 Allocating Arrays with new
Syntax:
Type* pointerName = new Type[size];
Example:
#include <iostream>
int main() {
int n;
std::cout << "Please enter the array size: ";
std::cin >> n;
// Allocate an array of n ints on the heap
int* arr = new int[n];
// Using the array
for (int i = 0; i < n; i++) {
arr[i] = i + 1;
}
// Output the array
for (int i = 0; i < n; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
// Freearray(Note:Use delete, not delete)
delete arr;
return 0;
}
💡 Key point: To free an array, use delete[] (with square brackets), not delete!
(2) 3.2 new and delete Must Be Paired Correctly
| Allocation | Deallocation |
|---|---|
new int |
delete p; |
new int[10] |
delete[] p; |
Error example:
int* p = new int[10];
delete p; // ❌ Error: Should use delete[] p;
4. Dangling Pointers
(1) 4.1 What is a Dangling Pointer?
A dangling pointer is a pointer that points to already freed memory.
#include <iostream>
int main() {
int* p = new int(5);
delete p; // Free memory
// ❌ Dangerous: p is now a dangling pointer
std::cout << *p << std::endl; // Undefined behavior! May output garbage or crash
return 0;
}
💡 Solution: Set the pointer to nullptr immediately after freeing:
delete p;
p = nullptr; // ✅ Good practice
5. Practice: Sorting a Dynamic Array
▶ Example 1: Selection Sort with a Dynamic Array (Difficulty ⭐⭐)
#include <iostream>
// Selection Sort
void selectionSort(int* arr, int n) {
for (int i = 0; i < n - 1; i++) {
int minIdx = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIdx]) {
minIdx = j;
}
}
// Swap
int temp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = temp;
}
}
int main() {
int n;
std::cout << "Please enter the array size: ";
std::cin >> n;
int* arr = new int[n]; // Dynamically allocate array
std::cout << "Please enter " << n << " Integer: " << std::endl;
for (int i = 0; i < n; i++) {
std::cin >> arr[i];
}
selectionSort(arr, n); // Sort
std::cout << "After sorting: " << std::endl;
for (int i = 0; i < n; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
delete[] arr; // Free memory
arr = nullptr;
return 0;
}
Output:
Please enter the array size:
Please enter Integer:
After sorting:
Running result:
Please enter the array size: 5
Please enter 5 Integer:
5 3 1 4 2
After sorting:
1 2 3 4 5
6. Common Errors
(1) 6.1 Double delete
Error example:
int* p = new int(5);
delete p;
delete p; // ❌ Error: Double free of same memory (undefined behavior)
Fix: Set to nullptr immediately after freeing (delete nullptr is safe).
delete p;
p = nullptr;
(2) 6.2 Forgetting delete
Error example:
int* arr = new int[10];
// ❌ Forgot to write delete[] arr;
Consequence: Memory leak.
❓ FAQ
▶ Example 3: Dynamic Array (Difficulty ⭐)
#include <iostream>
int main() {
int size = 5;
int* arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = i * 10;
}
for (int i = 0; i < size; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
delete[] arr;
return 0;
}
Output:
0 10 20 30 40
new int[n] allocates an array, delete[] frees an array. Don't forget the []!
- Stack: allocated at compile time, automatically freed, fixed size
- Heap: allocated at runtime, manually freed (
delete), variable size newallocates memory,deletefrees memorynew[]allocates arrays,delete[]frees arrays- Memory leak: forgetting
delete, serious consequences - Dangling pointer: points to freed memory, dangerous
📖 Summary
- new/delete: manually allocate/free memory
- new[]/delete[]: array memory allocation/deallocation
- Memory leak: forgetting to free causes resource waste
- Smart pointers: recommend using unique_ptr/shared_ptr as alternatives
📝 Exercises
-
Basic (Difficulty ⭐): Use
newto allocate adouble, assign it3.14, output it, then free it. -
Intermediate (Difficulty ⭐⭐): Let the user input
n, usenewto dynamically allocate anintarray of sizen, inputnintegers, find the maximum, then free the memory. -
Challenge (Difficulty ⭐⭐⭐): Implement a "dynamic array" class using dynamic memory (you'll learn classes later; use a struct for now):
-
Include:
int* data(pointer to heap array),int size(current size),int capacity(capacity) -
Implement a
push_backfunction: ifsize == capacity, reallocate a larger block of memory (newa larger array, copy data over, free the old one) -
Test: add 100 elements
- new allocates heap memory and returns a pointer
- delete frees memory allocated by new
- new[] allocates arrays, delete[] frees arrays
- Memory leak: using new without delete
- Allocation failure: new throws std::bad_alloc exception
11. 🚀 Next Step
Now that you've learned dynamic memory allocation, let's move on to Pointers and References: Comprehensive Practice (Lesson 27) — reinforcing everything you've learned through integrated examples!