In C++, variables can have different types of storage durations, each defining how the memory for the variable is allocated and deallocated.
Automatic variables are created on the stack and are automatically destroyed when they go out of scope, invoking the destructor.
void example() {
int x = 42; // Automatic variable
std::ofstream file("example.txt"); // Automatically cleaned up
} // `x` and `file` are destroyed hereDynamic variables are created on the heap using new and must be manually destroyed using delete, since the lifecycle is controlled explicitly by the programmer. Mistakes in lifecycle management leads to memory leaks or dangling pointers which can result in undefined behavior
void example() {
int* ptr = new int(42); // Allocated on the heap
std::cout << *ptr << std::endl;
delete ptr; // Must free the memory manually
}Static variables persist for the entire program lifetime and are cleaned up when the program exits.
void example() {
static int counter = 0; // Retains its value across function calls
counter++;
std::cout << counter << std::endl;
}Smart pointers like std::unique_ptr and std::shared_ptr automate memory
management for heap-allocated objects, reducing errors and simplifying code:
std::unique_ptrowns a resource exclusively and ensures it is released when the unique_ptr goes out of scope.std::shared_ptrallows shared ownership of a resource and its backed by a counter so that only after the counter goes to 0 the resource is destroyed
#include <memory>
void example() {
auto file = std::make_unique<std::ofstream>("example.txt");
*file << "Smart pointers simplify cleanup.";
} // Destructor for `file` automatically closes the file
void example() {
auto sharedFile = std::make_shared<std::ofstream>("example.txt");
{
auto sharedFile2 = sharedFile; // Shared ownership
*sharedFile2 << "Shared ownership example.";
} // `sharedFile2` is destroyed, but `sharedFile` keeps the resource alive
} // Resource is destroyed when `sharedFile` goes out of scope