RAII and Move Semantics: The Heart of Modern C++
By Eduardo Dionisio
C++ has no garbage collector, yet leaks are largely a solved problem. The two ideas behind that — RAII and move semantics — are the same ideas that separate modern C++ from C-with-classes.
RAII: resources tied to object lifetime
RAII (Resource Acquisition Is Initialization) means: acquire a resource in a constructor, release it in the destructor. When an object goes out of scope, its destructor runs automatically — on every exit path, including exceptions. This is why you should almost never write raw new/delete.
void read_config(const std::string& path) {
// Opens now, closes automatically when the function exits
std::ifstream file(path);
std::vector<std::string> lines;
std::string line;
while (std::getline(file, line)) {
lines.push_back(line);
}
// No manual close(), no leak if an exception is thrown
}Smart pointers own by default
- std::unique_ptr — single owner, movable but not copyable. Your default choice.
- std::shared_ptr — shared ownership via reference counting. Use sparingly.
- std::weak_ptr — a non-owning observer that breaks shared_ptr cycles.
Move semantics: cheap transfers, not copies
Copying a vector duplicates every element. Moving it just steals the internal pointer, leaving the source empty. std::move is a cast that marks an object as an rvalue, allowing the move constructor or move assignment to be selected. It does not move anything by itself — which is why moving a const object quietly falls back to a copy.
std::vector<int> a = make_huge_vector();
std::vector<int> b = std::move(a); // steals a's buffer, O(1)
// a is now valid but unspecified — treat it as emptyThe rule of thumb: if you're writing a destructor, a copy constructor, or an assignment operator by hand, you probably want the others too (the Rule of Five). If you're not, the compiler-generated defaults are usually correct — trust RAII and let the language manage ownership.