Map

RAII

Wiki conceptcppmemory-managementlanguage-design โ†ณ show in map Markdown
title
RAII
type
concept
summary
Resource Acquisition Is Initialization โ€” bind resource lifetime to object lifetime so cleanup runs deterministically when the object goes out of scope
tags
cpp, memory-management, language-design
created
2026-05-08
updated
2026-05-08

RAII โ€” Resource Acquisition Is Initialization โ€” is the discipline of tying a resource's lifetime to an object's lifetime. The constructor acquires the resource (memory, file descriptor, lock, socket); the destructor releases it. As long as the object is destroyed deterministically, the resource is released deterministically. No try/finally. No paired-call discipline at every call site.

The name is misleading enough that even Stroustrup later called it a poor choice โ€” what matters is the destructor running, not the constructor doing acquisition. "Scoped resource management" describes it more honestly. But the acronym stuck.

The shape

A type wraps a resource. Its constructor acquires; its destructor releases; copy and move semantics make ownership explicit at the type level. Anyone holding the object holds the resource; when the object dies, the resource is freed. C++ destructors fire on scope exit, on exception unwinding, on container element removal, and on smart-pointer reset โ€” uniformly, without programmer attention.

The standard library's unique_ptr, shared_ptr, lock_guard, fstream, vector, and string are all RAII types. So is every Rust type with a Drop impl โ€” Rust took RAII as a baseline and made it the only memory-management story.

Why it works

The argument stroustrup-memory-leaks makes is operational, not aesthetic: a human can track a few dozen objects, not tens of thousands of allocations. RAII collapses the bookkeeping. Once a resource has an owner, the question of who frees it becomes the question of who owns it, and ownership is visible at the type signature. Pointer-arithmetic code answers neither question; RAII code answers both by construction.

This generalizes beyond memory. File handles, mutex locks, database transactions, GPU resources, and reference counts all share the acquire/release pattern. RAII is the encoding of that pattern in the type system.

What it requires from the language

RAII needs deterministic destruction โ€” destructors that fire at known points (scope exit, container removal, smart-pointer reset), not "eventually, when GC notices." Languages with non-deterministic finalizers (Java, Python, Go) cannot do RAII directly; they fall back to try-with-resources, with blocks, or defer, all of which require the programmer to remember to opt in.

Garbage-collected languages can manage memory without RAII because memory is fungible โ€” slightly delayed reclamation is fine. They cannot manage non-fungible resources (file handles, locks, network sockets) the same way, which is why Java grew try-with-resources and Python grew context managers. RAII is the C++/Rust answer to the same problem, applied uniformly.

Connections

  • stroustrup-memory-leaks โ€” the canonical short statement of RAII as memory-leak prevention
  • simplified-model-of-fil-c โ€” Fil-C bolts memory safety onto C/C++ via GC because the discipline of RAII isn't enforceable in legacy code
  • pointer-provenance โ€” pointers carry allocation identity; RAII puts that identity inside an owning type
  • no-silver-bullet โ€” RAII is one of the rare attacks on accidental complexity that produced an order-of-magnitude reduction in a specific bug class
Sub-pages