RAII ties a resource’s cleanup to an object’s lifetime. A guard’s destructor releases the resource when its scope ends, including when an exception interrupts normal execution. section 2.1.3 section 3.2.1
Listing 2.3. Using RAII to wait for a thread to complete
class thread_guard
{
std::thread& t;
public:
explicit thread_guard(std::thread& t_):
t(t_)
{}
~thread_guard()
{
if(t.joinable())
{
t.join();
}
}
thread_guard(thread_guard const&)=delete;
thread_guard& operator=(thread_guard const&)=delete;
};
struct func; #1
void f()
{
int some_local_state=0;
func my_func(some_local_state);
std::thread t(my_func);
thread_guard g(t);
do_something_in_current_thread();
}
A thread_guard joins its thread in the destructor; scope-based destruction also runs when the function exits by exception. section 2.1.3
For mutexes, std::lock_guard locks on construction and unlocks on destruction, avoiding manual unlocks on every exit path. section 3.2.1



