Normally, when you declare a variable, its memory is allocated on the stack. The stack is fast and automatic — variables are created when a function runs and destroyed when it returns. But the stack has limited size. When you need memory that lives beyond a function call, or when you need larger chunks, you turn to the heap.
new and delete
The new keyword allocates memory on the heap and returns
a pointer. The delete keyword frees that memory. Every
new must be matched with a delete — otherwise
you have a memory leak.
#include <iostream>
int main() {
int* p = new int;
*p = 77;
std::cout << "Dynamically allocated value: " << *p << "\n";
delete p;
int* arr = new int[5];
for (int i = 0; i < 5; i++) {
arr[i] = (i + 1) * 10;
}
std::cout << "Array elements: ";
for (int i = 0; i < 5; i++) {
std::cout << arr[i] << " ";
}
std::cout << "\n";
delete[] arr;
return 0;
}
Use delete for a single object and delete[]
for an array. Mixing them up is undefined behavior.
Stack vs Heap
Stack memory is managed automatically — variables are popped off when they go out of scope. Heap memory stays until you explicitly free it. That is why heap allocation is more flexible but also requires more responsibility.
#include <iostream>
int* createOnHeap() {
int* ptr = new int(999);
return ptr;
}
int main() {
int* result = createOnHeap();
std::cout << "Heap value: " << *result << "\n";
int stackVar = 100;
std::cout << "Stack value: " << stackVar << "\n";
delete result;
return 0;
}
The createOnHeap function returns a pointer to heap memory
that survives after the function exits. A stack variable like
stackVar would be destroyed when its function ends.
Dangling Pointers
After you delete a pointer, the memory is freed but the
pointer still holds the old address. Using it causes undefined behavior.
Always set deleted pointers to nullptr:
#include <iostream>
int main() {
int* p = new int(50);
delete p;
p = nullptr;
if (p == nullptr) {
std::cout << "Pointer is safely null\n";
}
return 0;
}