We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← RAII: Objects With Lifetimes step 1 of 4
The destructor is the whole idea
C++ has one genuinely great idea and this is it.
When an object goes out of scope, its destructor runs. Always. On the normal path, on an early
return, and while an exception is unwinding.
That guarantee is worth more than it first sounds, because it lets you attach
any cleanup to any scope and stop thinking about it. Close a file. Release
a lock. Free memory. Commit or roll back a transaction. Restore a setting you
changed. None of them need a finally, because the language already runs
something at the end of every block, unconditionally.
The name is RAII — Resource Acquisition Is Initialisation — which is a famously bad name for a good idea. Read it as: a resource’s lifetime is an object’s lifetime.
The two rules you need today
1. Destruction is the reverse of construction. Within a scope, objects are destroyed in the opposite order to the one they were created in:
{
Logger a{"a"}; // constructed 1st
Logger b{"b"}; // constructed 2nd
} // b destroyed 1st, then a
This is not an implementation detail — it is guaranteed, and it is what makes
it safe for b to depend on a. Anything you build later can rely on
anything you built earlier still being alive.
2. It happens on every exit. Including the ones you did not write:
{
Logger a{"a"};
if (bad) {
return; // a is destroyed here
}
might_throw(); // if this throws, a is destroyed as the stack unwinds
} // and here on the normal path
Compare this to a language where you write try { ... } finally { close(); }
around every acquisition. The C++ version puts the cleanup next to the
resource, once, in the type — and then no caller can forget it, because
forgetting is not something a caller is able to do.
Your task
A Tracer type is given to you. Its constructor appends "+name" to a log
and its destructor appends "-name". Nothing to change there.
std::vector<std::string> run(const std::vector<std::string>& names, int stop_after);
Create one Tracer per name, in order, each inside a nested scope so that
it is destroyed before the next one is created — so the log reads
+a, -a, +b, -b, … rather than all the constructions followed by all the
destructions.
If stop_after is reached, return early. The already-created tracers must
still be destroyed, in the right order, and if you have written it correctly
you will not have to do anything to make that happen.
Return the log.
Stuck?
C++ reference solution
Sign in to attempt this problem and reveal the reference solution.