Modern Memory Management
Modern Memory Management
Replace manual ownership with RAII and smart pointers.
Modern Memory Management
Replace manual ownership with RAII and smart pointers.
Widget* widget = new Widget();
// ...
delete widget;
This style is error-prone because exceptions, multiple return paths, or missed deletes can leak memory.
auto widget = std::make_unique<Widget>();
The object is automatically destroyed when the owning smart pointer goes out of scope.
That is the normal modern path: prefer stack allocation first, then std::unique_ptr when the object truly needs dynamic lifetime.
Use std::shared_ptr only when several objects truly co-own the same resource.
auto config = std::make_shared<Config>();
start_worker(config);
start_logger(config);
This is appropriate when multiple long-lived parts of the program must keep the same object alive independently.
std::unique_ptr secondstd::shared_ptr only when requiredstd::unique_ptr<Widget> make_widget() {
return std::make_unique<Widget>();
}
void install(std::unique_ptr<Widget> widget) {
current_widget = std::move(widget);
}
Passing std::unique_ptr by value is a clean way to express ownership transfer.
Shared ownership can hide lifetime relationships. It also introduces atomic reference counting overhead and can create cycles.
struct Node {
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev;
};
Use std::weak_ptr to break cycles in graph-like structures.
If both directions used std::shared_ptr, two nodes could keep each other alive forever even after the rest of the program released them.
struct Person {
std::string name;
std::shared_ptr<Person> partner;
};
This kind of cycle leaks until one side becomes std::weak_ptr.
struct Person {
std::string name;
std::weak_ptr<Person> partner;
};
Owning types manage lifetime. Borrowing types such as std::span and std::string_view only observe data. This distinction is one of the most important modern C++ habits to internalize.
void draw(std::span<const Pixel> pixels);
void greet(std::string_view name);
Borrowing APIs are powerful, but the caller must keep the underlying data alive for the duration of the use.
RAII is what makes exception-safe code ordinary rather than special. Acquire resources into objects immediately so cleanup always happens on every path.
std::unique_ptr.std::shared_ptr?#include <memory>
int main() {
auto value = std::make_unique<int>(42);
return *value;
}
Transfer ownership out of one scope and into another with `std::move`. It is the fastest way to see what unique ownership really means.
#include <memory>
std::unique_ptr<int> make_value() {
auto value = std::make_unique<int>(42);
return value;
}