The problem with manual delete
Pairing every new with a delete sounds easy until real code intervenes:
void process() { int* buf = new int[1000]; if (loadFailed()) return; // oops: leaked, delete never runs // ... an exception here also skips the delete ... delete[] buf; }
Every early return, break, or exception is a path that can skip the cleanup line. Chasing all paths by hand does not scale.
The C++ answer: RAII
RAII (Resource Acquisition Is Initialization) means: wrap the resource in an object, acquire it in the constructor (code that runs when the object is created), release it in the destructor (code that runs automatically when the object's scope ends). The language guarantees the destructor runs on every exit path.
Unit 7 teaches you to write constructors and destructors yourself. First, meet the standard library's ready-made RAII wrapper for heap memory.
std::unique_ptr
std::unique_ptr<T> (from <memory>) is a pointer-sized object that owns one heap allocation and deletes it in its destructor:
#include <memory> void process() { auto buf = std::make_unique<int[]>(1000); // heap array, owned buf[0] = 42; if (loadFailed()) return; // fine: destructor frees it } // fine: destructor frees it here too
std::make_unique<T>(args)allocates and wraps in one step. No rawnewin sight.- Use it like a pointer:
*p,p->member, orbuf[i]for the array form. autoasks the compiler to deduce the variable's type from the right-hand side, sparing you writingstd::unique_ptr<int[]>out.- Unique means exactly one owner: a unique_ptr cannot be copied, only moved to a new owner with
std::move.
The modern rule: new/delete are for understanding and for interviews about internals. In code you write, prefer unique_ptr, and even more often prefer containers like std::vector (unit 8), which are RAII wrappers around arrays.
Code exercise · cpp
Run this. The unique_ptr frees its int automatically, and the tiny Probe struct proves destructors run at scope exit: its message prints even though nobody calls anything at the end.
Quiz
Why is unique_ptr's cleanup more reliable than writing delete yourself?
Code exercise · cpp
Your turn. Rewrite this leaky raw-pointer code to use std::make_unique<int>(...) instead of new, and remove the (missing!) delete problem entirely. Output must stay `total: 30`.