Constructors, Destructors & RAII
c2-2 was the C track's own central chapter: manual malloc/free, with every allocation carrying real risk of a forgotten free. This chapter is C++'s answer — and, genuinely, it's the same answer Rust would later give.
RAII — Resource Acquisition Is Initialization
The core idea: tie a resource's lifetime directly to an object's lifetime. Acquire the resource in the constructor; release it in the destructor. When the object goes out of scope — through any exit path, including an early return or an exception — the destructor runs automatically, releasing the resource with zero remaining programmer effort at that point.
A Worked RAII Example — A Simple Owning Wrapper
Compare this directly against c2-2's own discipline: "every allocation needs a matching free, and the programmer must remember every single time." Here, allocate once in the constructor, and never have to remember to free again — the destructor handles it unconditionally, even during an exception unwind.
The Direct Rust Parallel
This is, genuinely, exactly Rust's Drop trait — invented roughly fifteen years earlier, via manual class-writing instead of a language-level trait system. Rust's own ownership model (rust1-3) and smart pointers (rust2-2) were historically compared to, and influenced by, this exact C++ idiom. A real, rare moment of genuine convergent evolution between the two languages, unlike most of the C track's own contrasts.
new and delete
C++'s own heap-allocation operators — a real, concrete improvement over C's malloc/free. new allocates and calls the constructor automatically; delete calls the destructor and frees the memory. Raw malloc/free know nothing about object lifecycles at all — just bytes.
Mismatching them — new with delete[], or vice versa — is undefined behavior, the exact same category c3-4 covered in full.
The Rule of Three, Previewed
A class managing a resource manually generally needs a destructor, a copy constructor, and a copy assignment operator together — or copies of the object risk a double-free exactly like c2-3's own bug catalog. Full depth arrives in cpp2-8; this is just the forward pointer.
Exception Safety, Briefly
RAII's other major payoff, previewed ahead of cpp2-6's own Exception Handling chapter: because destructors run on any scope exit — including an exception unwinding through the call stack — RAII-managed resources are cleaned up automatically even when an error is thrown mid-function. C's manual cleanup pattern has no equivalent mechanism at all; C has no exceptions and no automatic stack unwinding.
| Concept | C (c2-2) | C++ RAII | Rust |
|---|---|---|---|
| Resource release | manual free() — programmer must remember | automatic — destructor on scope exit | automatic — Drop on scope exit |
| Cleanup on an error mid-function | no mechanism — manual only | automatic — destructors run during unwinding | automatic — Drop runs even on panic unwind |
| Allocation + initialization | two separate manual steps (malloc, then init) | one step — new calls the constructor | one step — the constructor pattern is the norm |
IntArray is a teaching device. Course 2's smart pointers (unique_ptr/shared_ptr) are the standard, battle-tested RAII wrappers real code should reach for — reinventing them by hand is rarely the right call outside a learning exercise.
cpp2-6 introduces exceptions in full.
Coding Challenges
Write a class that acquires a resource (e.g. allocates an int array with new[]) in its constructor and releases it with delete[] in its destructor. Create an instance inside a nested scope and print a message from both the constructor and destructor to observe the order they run in.
📄 View solutionAllocate an object with new, then intentionally never call delete on it. Explain, referencing c2-2's own material, what class of bug this is and why RAII alone doesn't protect against this specific mistake.
📄 View solutionExplain precisely why RAII is considered the same underlying idea as Rust's Drop trait, and name the one concrete mechanical difference between how each language actually triggers the cleanup code.
📄 View solutionChapter 5 Quick Reference
- RAII — acquire in the constructor, release in the destructor, tied to object lifetime
new/delete— allocate+construct / destruct+free in one step, unlike raw malloc/freenew[]must be matched withdelete[]— mismatching is undefined behavior- Destructors run on any scope exit, including exception unwinding — C has no equivalent mechanism at all
- This is genuinely the same idea as Rust's
Drop, roughly fifteen years earlier - Next chapter: operator overloading — giving custom types +, ==, and <<