What it did
The C++ nanodegree’s “Memory Management” module ends with a chatbot
project that’s intentionally full of raw pointers, manual new/
delete, and ownership ambiguity. The work is to refactor it so every
allocation matches a single smart-pointer pattern, with zero leaks.
Specifically the task is to apply each of the 5 ownership models:
| Rule | Example in the chatbot |
|---|---|
Exclusive ownership (unique_ptr) | Each GraphNode owns its ChatBot instance |
Shared ownership (shared_ptr) | A ChatLogic shared across the GUI + the graph |
Weak observation (weak_ptr) | Edges back-referencing nodes (avoids cycles) |
| Move-only resources | The chatbot image (large) moves into nodes, not copies |
| Rule of Five | ChatBot itself implements full copy/move ctor + assignment |
What was actually tricky
- The Rule of Five is not optional once you hold a raw pointer that owns its target. If you declare any of (dtor, copy ctor, copy assign, move ctor, move assign), you almost always need all five. The compiler doesn’t tell you; the leaks at runtime do.
unique_ptrmove semantics + STL containers. Avector<unique_ptr<T>>doesn’t allow copy — you muststd::moveduring emplacement. The compiler error is enormous and not helpful.- Cycles in the graph. Each node has children + parents. If both
are
shared_ptr, the ref-count never drops to 0. The fix isweak_ptrfor one direction (usually parent).
What I’d do differently with hindsight
- Skip raw pointers entirely. The cleanest modern-C++ codebases
use smart pointers from the start and never construct anything
with
new. The project’s pedagogical value is “see what the manual ownership feels like,” which is exactly the thing you shouldn’t reach for in production. - Sanitizers always. Compile with
-fsanitize=address+-fsanitize=leakduring development; they catch ownership bugs immediately instead of in mysterious crashes hours later. - Don’t use wxWidgets. The GUI layer is mostly historical baggage in the project. A modern CLI version (or Dear ImGui) would let the lesson focus on memory ownership instead of widget binding.
What it taught me
C++ memory ownership is a graph problem, not a syntax problem. The
question is never “where do I put new?” — it’s “what’s the
ownership tree, and where are the cycles?” Once that’s clear, the
smart-pointer choices are mechanical. Most C++ bugs in my code
since this project have been ownership-graph bugs, not pointer-
arithmetic bugs.