Memory · Memory & ownership

RAII & resource lifetime

Make cleanup part of an object’s lifetime.

Let an object carry the cleanup.

RAII ties a resource to an owning object. Construction establishes ownership, and destruction releases the resource. A local owner is destroyed when its scope ends, so cleanup follows the structure of the program instead of relying on every exit path remembering it.

Exit paths multiply. Cleanup should not.

A function may finish normally, return early, or unwind because of an exception. Fully constructed automatic objects in exited scopes are destroyed during these normal C++ cleanup paths. A resource wrapper puts cleanup in one destructor. This does not promise cleanup after abrupt process termination.

The owner lives in this function.

unique_ptr owns the integer. Either return leaves the function’s scope and destroys that owner, which deletes its integer. No separate cleanup statement is needed at either return.

int readValue(bool useIt) {
    auto value = std::make_unique<int>(42);
    if (!useIt) return 0;
    return *value;
}

Acquire → use → release.

The resource’s cleanup is attached to the owner’s lifetime. The owner can be an automatic object even when the resource itself is dynamically allocated.

Construct an owner, use its resource, then release the resource when the owner is destroyed.
Construct owner
acquire resource
Inside scope
use resource
Destroy owner
release resource
  • Construct owner leads to Inside scope
  • Inside scope leads to Destroy owner

Resources are more than bytes.

A lock_guard unlocks a mutex when the guard is destroyed. A file stream closes its file when it is destroyed. The shared pattern is ownership with a deterministic release action. Garbage collection for memory alone would not express when a mutex should be unlocked.

Further reading

Trusted resources for the rules and APIs discussed in this guide.