Chapter 11 · Week 11

Pointers, this, and Dynamic Memory

"Therefore, since we are surrounded by so great a cloud of witnesses..." — Hebrews 12:1
11

Watch the pointers rewire

A linked list is a chain of nodes connected by pointers. Add, remove, insert, reverse — watch the arrows move. This is exactly what your destructor will walk to free everything in Project 11.

Linked List Playground — Chain of Witnesses

Real witnesses from the historical chain of Christian testimony, held in memory as a singly linked list. Click the operations to add, remove, insert, or reverse. Watch the pointer arrows rewire — that's what your destructor will eventually traverse to free everything.

head →
SIZE 0 HEAD (null) TAIL (null)
What the destructor has to do: walk from head, save node->next, delete node, move to the saved next. Forget any of those steps and you either crash on use-after-free or leak the rest of the chain. Project 11 makes you do this by hand — with valgrind verification of zero leaks.

Why This Matters

For ten chapters you have used variables that the compiler put somewhere in memory without telling you where. This chapter takes the hood off.

A pointer is a variable whose value is the memory address of another variable. With pointers you can refer to things without copying, build data structures whose size is decided at runtime, and access the same data from multiple places.

For the apologetics theme: the chain of historical Christian witness. From the Apostles, through the Apostolic Fathers (Clement, Ignatius, Polycarp), through the early Church Fathers, the Reformers, the modern Church — each generation pointed back to the one before. A linked list, naturally. (Note: this is the historical continuity of public testimony, not Roman-style apostolic succession — that's a different doctrinal claim.)

Three Pointer Operations

  • &x — "address of x" (produces an int* when x is an int)
  • *p — "the int that p points to" (dereference)
  • p->field — when p points to a struct/class, access a field
int x = 42;
int* p = &x;     // p holds the address of x
cout << *p;      // 42 — dereference
*p = 100;        // modify x through p
cout << x;       // 100

new and delete

For memory whose lifetime you control yourself:

Witness* w = new Witness;
w->name = "Polycarp";
w->century = 2;
// ... use w ...
delete w;        // free the memory when done
w = nullptr;     // defensive: future *w would crash, but at least we know why

Every new must have a matching delete on every code path. Forget the delete and you've leaked memory. Programs that leak eventually run out. AddressSanitizer (compile with -fsanitize=address) will catch leaks reliably.

Self-Referencing Structures (Linked Lists)

struct Witness {
    string name;
    int century;
    Witness* next;     // pointer to the next witness in the chain
};

Each witness knows who comes next. The last one has next = nullptr. To traverse:

Witness* current = head;
while (current != nullptr) {
    cout << current->name << endl;
    current = current->next;
}

That loop is the canonical pattern. The widget above does exactly this on every render.

The Destructor's Job

~Chain() {
    Node* current = head;
    while (current != nullptr) {
        Node* next = current->next;   // save before delete
        delete current;
        current = next;
    }
}

Save next before delete. Forget to save and you've just freed the node whose next pointer you were about to dereference. Classic use-after-free bug.

Coach's Note — This is the technical hardest chapter in the course. Pointers, manual memory management, linked structures are the bedrock of the language. If Chapter 11 takes you twice as long as the others, that's normal. Slow down. Draw the lists on paper. Java's garbage collector (Chapter 13) will feel like a gift after this.

This Week's Project

You're ready for Project 11: Chain of Witnesses. Build a singly linked list of real historical Christian witnesses with add/remove/print/destructor. Stress test with 100 nodes. Verify zero memory leaks via AddressSanitizer. Do not invent quotes — every witness must have a real, attributable testimony.

Check Your Reps

Pointers — Quick Check

Question 1 of 4
What does this print?
int x = 42;
int* p = &x;
*p = 100;
cout << x;
Why: p holds the address of x. *p = 100 dereferences p (gets to the int it points to) and assigns 100. Since p points to x, this modifies x through the pointer. x is now 100.
Question 2 of 4
What's the bug here?
Node* current = head;
while (current != nullptr) {
    delete current;
    current = current->next;
}
Why: After delete current, the memory at that location is no longer ours — reading current->next is undefined behavior. The fix is to save next before deleting:
Node* next = current->next; delete current; current = next;
Question 3 of 4
You forget the delete at the end of a function that called new. What happens?
Why: C++ won't catch the leak at compile time or runtime — the memory is simply never freed. Programs that leak in a loop eventually exhaust memory and crash. Run with -fsanitize=address (AddressSanitizer) to catch these in development.
Question 4 of 4
Project 11 asks you to build a Chain of Witnesses. Which framing is the project using?
Why: The project models the historical record: real witnesses across centuries who taught and testified to the same gospel. That's an empirical, checkable claim. It does NOT model Roman-style apostolic succession — that's a sacramental doctrine the confessional Lutheran tradition the textbook is written for rejects. The Coach's Note in the project spec explicitly draws this line.
YOU FINISHED. NICE WORK.

← WEEK 10: CONSTRUCTORS   ·   WEEK 12: INHERITANCE →