7 routes42 sections324 units

Unit 7.4 · about 6 h

45 / 324

Storage duration, RAII, smart pointers and move semantics

A buffer can be correctly indexed and still be dead. RAII makes cleanup follow ownership, including failure paths that are easy to miss with manual deletion.

  • explain
  • implement

You can now

  • Distinguish storage duration from the lifetime and ownership of an object in that storage.
  • Predict destruction and resource release through normal returns and caught exceptions.
  • Implement an owning buffer with independent-copy, ownership-transfer and checked-access tests.

Covers

  • Stack and heap storage duration and allocation
  • RAII, ownership and smart pointers
  • Copy, move and object lifetime through exceptions

Study, in this order

6 steps

  1. Stack vs Heap
    AlgoMaster C++

    The Stack: Automatic and LIFO; The Heap: Dynamic and Manual; When to Use the Stack vs the Heap

    Depth · Skip address-region diagrams and Performance Differences. Automatic and dynamic storage duration are language concepts, not guarantees about placement or allocation speed.

  2. RAII Pattern
    AlgoMaster C++

    The Core Idea through Hand-Rolled Cleanup vs RAII Under Exceptions; A Note on the Rule of Three; Almost Always RAII

  3. Exclusive ownership
    AlgoMaster C++

    Constructing a unique_ptr; Move-Only Semantics; The Common Operations; Arrays with unique_ptr<T[]>

  4. Shared ownership and observers
    AlgoMaster C++

    When Shared Ownership Actually Makes Sense; The Control Block; Thread Safety, Precisely; What This Chapter Does Not Cover

  5. Copy and move contracts
    AlgoMaster C++

    The Move Constructor Signature through When the Compiler Generates a Move Constructor; A Complete Example: Cart with Move and Copy

    Depth · Skip the introductory claim that return-by-value necessarily copies and Exercise 7's unconditional noexcept rule. Copy elision can remove transfers, and vector can move a noncopyable element even if its move may throw.

  6. RAII and special members
    C++ Core Guidelines

    R.1: Manage resources automatically using resource handles and RAII; C.20: If you can avoid defining default operations, do; C.21: If you define or delete any copy, move, or destructor function, define or delete them all

Focus on

  • An automatic smart-pointer handle can own a dynamically allocated object. The handle and the allocation have separate lifetimes.
  • Scope exit and exception unwinding destroy fully constructed automatic objects in reverse construction order. A constructor that throws does not run that object's destructor, but already constructed members and bases are unwound.
  • Prefer vector and the Rule of Zero for ordinary buffers. If you manage a raw resource, state copy and move contracts for constructors and assignment, and leave the moved-from object safe to destroy.
  • unique_ptr expresses exclusive ownership. shared_ptr shares ownership, not synchronization of the pointee; weak_ptr observes without forming a strong ownership cycle.

Reproduce closed-book

With g++ 15.2 -std=c++20 -O0 -g, construct two local logging guards A then B inside a try block and throw std::runtime_error to an outer catch. Print only names from destructors and 'catch' from the handler: the sequence is B A catch. Separately move make_unique<int>(7) into a second unique_ptr and assert the first is null and the second holds 7. Implement a vector-backed Buffer with a deep-copy contract, a custom move that resets the source to an empty state, and access that throws std::out_of_range for i >= size(). Check copy independence, move construction, move assignment, self-assignment, empty access and a caught exception after allocation. Keep the checks active in optimized builds; do not rely only on assert when NDEBUG is set.

Traps

  • std::move is a cast that enables move overloads. It does not itself transfer resources; moving from a const object can select a copy.
  • A shared_ptr reference count does not collect strong cycles or protect mutable data from concurrent access.
  • RAII is not a promise of cleanup after process termination, std::abort or every uncaught exception. Test ordinary scope exit and caught unwinding.

Practice

AlgoMaster Exercise: RAII

Exercises 1 to 5: scoped release, closing on every return path, unlocking during unwinding, rolling back an uncommitted transaction and restoring a global setting after an exception

Predict the printed acquire and release order before running each one.

AlgoMaster Exercise: Copy-and-Swap Idiom

Exercises 2 to 4: deep copy for copy-swap assignment, one by-value operator for copy and move, and leaving the target unchanged when copying throws

Carry the deep-copy and failed-copy checks into the owning Buffer tests.

Self-test

  1. A constructor acquires two resources but the second acquisition throws. How should the first be protected?

  2. Does copying a raw owning pointer produce an independent buffer?

  3. After moving a unique_ptr into another, which one owns the object?

  4. Must a return-by-value function always call a copy or move constructor?

Completion criterion

Stop when

You predict the guard destruction trace and your buffer tests demonstrate independent copies, an explicitly empty moved-from state and cleanup through a caught exception.

Mark passed, then open 7.5 Only mark this when you can do it without notes.

Leads to

Comes after

Resources for this unit

  • AlgoMaster C++
    AlgoMasterprimarycourse
    Use the sections on compilation, pointers and references, memory, RAII and smart pointers, copy and move, STL containers, templates, errors, concurrency and paired exercises. Skip competitive-programming breadth already covered in Algorithms.
  • C++ Core Guidelines
    Standard C++ Foundation communityrequiredreference
    Use the Philosophy, Interfaces, Resource management, Expressions, Containers and concurrency rule groups to review ownership and safety decisions in the native component.

Also in this section

  • cppreference
    cppreference communitysupportreference
    Consult language lifetime, object model, value categories, memory model, atomics, containers and iterator invalidation while reading or modifying code.
  • Clang AddressSanitizer and UndefinedBehaviorSanitizer
    LLVMrequiredimplementation
    Compile seeded memory defects with AddressSanitizer and UndefinedBehaviorSanitizer, preserve the reports, repair the root cause and keep regression tests.
  • pybind11 documentation
    pybind11 projectrequiredimplementation
    Follow First steps and NumPy support to expose one small native function with explicit shape, dtype, stride, ownership, GIL and exception behavior.
  • CMake tutorial
    CMakesupportimplementation
    Use the introductory steps for targets, libraries, testing and install rules. Produce one clean debug build and one optimized build without copied one-off commands.
  • Algorithmica - AoS and SoA
    Sergey Slotinsupportapplication
    Read the AoS and SoA experiment for a measured case where keeping each record together wins, the counterpart to a single-field scan.
  • `ld.so`: dynamic linker/loader
    Linux man-pages projectsupportreference
    Read DESCRIPTION, Dynamic string tokens and LD_DEBUG to distinguish link-time symbols from runtime shared-library discovery on Linux.
  • Memory Layout Transformations
    Intelsupportreference
    Read Overview and Topics through AOS Form and SOA Form for field-wise access and locality trade-offs. Skip Intel array-notation syntax and the LIBOR example.
  • GDB manual: Backtraces
    GNU Projectsupportreference
    Use section 8.2 for frame numbers, bt, bt -full and optimized-out arguments when inspecting a native failure.

Quick find

Search Michi

Type to search every route, section, unit, topic and resource.

Enter opens the first result Esc closes

Reference

Keyboard shortcuts

n
Continue to the first unit not passed
j / k
Next / previous unit
1 2 3
Toggle learned, practised, passed
/
Open search
?
Show this help
Esc
Close open panels