Module 11 — Summary¶
The essentials¶
- RAII ties release to scope exit — acquire in a constructor, release in a destructor. It is the only mechanism guaranteed to run on every way out of a scope, including the one taken while an exception is propagating, and it therefore applies to files, locks, sockets and connections exactly as it applies to memory.
- A raw pointer says nothing about ownership. Smart pointers put the answer in the type, where the compiler enforces it and where every reader can see it without reading a body.
unique_ptris the default for exclusive ownership: move-only, effectively free (sizeofequals a raw pointer), and its deleted copy is a feature — a second owner cannot exist. Create one withmake_unique, never withnew.shared_ptris for ownership that genuinely cannot be attributed to one owner. It costs a second pointer and a control block, and its reference count protects the count, not the object. "Thread-safe count" does not mean "thread-safe object".weak_ptrobserves without owning.lock()gives you a temporary owner if the object still exists;expired()answers a question you should not then act on. Check-then-use is a race; lock-then-use is not.- Cycles leak, silently. Two
shared_ptrs that own each other can never reach a zero count, so no destructor runs. A leak checker calls this memorystill reachable, which is why cycles survive review and testing: nothing is invalid, so nothing is reported. - One object, one control block.
shared_ptr<T>(raw)creates a second control block and therefore a second delete.make_shared,enable_shared_from_thisand a factory that returnsshared_ptrare how you guarantee one. - Borrow, do not own. Take
const T&,T&orT*when the callee is not taking ownership; take an owning pointer by value only to transfer. Ashared_ptrparameter on a function that stores nothing is a false promise with a real cost. - Polymorphic containers need owning pointers and a virtual destructor — Modules 7 and 11
meeting. A
std::vector<std::unique_ptr<Base>>holds several kinds and cleans them all up with no destructor written for the container. - Ownership bugs are mostly legal, so the technique is measurement: counters on acquisition and release, an instance counter on the type while you develop it, and a sanitizer for the subset of bugs that are actually invalid.
The one-sentence version¶
Put every resource inside an object whose destructor releases it, say who owns this in the type rather than in a comment, and then cleanup is not something you remember — it is something the compiler and the language guarantee.
Terms you must now be able to define¶
RAII · automatic cleanup · scope / stack unwinding · resource · ownership ·
borrow · unique_ptr · make_unique · shared_ptr · make_shared ·
control block · reference count · weak_ptr · lock() / expired() ·
reference cycle · still reachable · enable_shared_from_this · custom deleter ·
noexcept destructor · Rule of Zero achieved
All of them are defined in the glossary under this module.
Before you move on¶
- [ ] All core exercises attempted, with the results checked — including the two counter runs
- [ ] The lab builds with no warnings, and its throwing run is captured alongside the normal one
- [ ] The cycle was reproduced on purpose, with the destructor silence recorded
- [ ] Quiz score ≥ 80%, and every miss explained
- [ ] At least one challenge problem attempted, with the trade-off written down
- [ ] Skills checklist ticked, with the evidence for each item
- [ ] I can read any declaration and say who owns what — and where the type does not say it, I know that it does not
Where this goes next¶
Module 12 — Templates multiplies every decision on this page. A
template written for one record kind must be correct for another, which means it must be correct for
any ownership model those kinds use: whether they can be copied, whether their moves are noexcept,
whether they own resources at all. Lab 12 asks for one Repository<T> serving two kinds of record,
and the first question it raises is whether your types can be copied — which is exactly what Modules
10 and 11 settled.
Module 13 — Exception Handling is where this module's property becomes essential rather than tidy. Exception safety is defined in terms of what happens during unwinding, and the only thing guaranteed to happen during unwinding is a destructor. If release is not tied to a destructor, a failure path cannot be made correct at all.
Further reading¶
- Effective Modern C++, Scott Meyers — the items on
unique_ptr,shared_ptr,weak_ptrandenable_shared_from_thisare the definitive treatment of this module, and the source of several of its mistakes. - A Tour of C++ (3rd ed.), Bjarne Stroustrup — resource management presented as the language's central idea rather than as a library detail.
- The C++ Core Guidelines, sections on resource management and ownership — the rules this module teaches, stated as rules, with the reasoning attached.
See Further Reading for the full list, with what each source is good for and when to reach for it.