C++ Concurrency (std::thread) Cheat Sheet
Covers creating and managing std::thread objects, passing arguments safely, join versus detach semantics, and thread lifecycle pitfalls.
2 PagesIntermediateMar 30, 2026
Creating Threads
Spawn a thread from a function, lambda, or callable object.
cpp
#include <thread>void task(int id) { std::cout << "Thread " << id << " running\n";}std::thread t1(task, 1); // function + argsstd::thread t2([] { std::cout << "lambda\n"; }); // lambdastruct Functor { void operator()() { std::cout << "functor\n"; }};std::thread t3(Functor{});t1.join();t2.join();t3.join();
Passing Arguments
Arguments are copied into the thread by default; use std::ref for references.
cpp
void modify(int& value) { value *= 2; }int x = 10;// std::thread t(modify, x); // ERROR: would copy x, function expects int&std::thread t(modify, std::ref(x)); // pass by reference explicitlyt.join();std::cout << x; // 20// Move-only arguments must be moved instd::unique_ptr<int> p = std::make_unique<int>(5);std::thread t2([](std::unique_ptr<int> up) { std::cout << *up; }, std::move(p));t2.join();
join() vs detach()
Decide how a thread's lifetime relates to the spawning thread.
cpp
std::thread worker(longRunningTask);worker.join(); // blocks the current thread until worker finishes// ORworker.detach(); // worker runs independently; caller no longer manages it // detached threads must not access destroyed local state// Both throw std::system_error if called on a thread that's not joinableif (worker.joinable()) { worker.join();}// RAII wrapper to guarantee join on scope exit (avoids std::terminate)struct ThreadGuard { std::thread& t; ~ThreadGuard() { if (t.joinable()) t.join(); }};
Thread IDs & Hardware Concurrency
Identify threads and query available parallelism.
cpp
std::cout << std::this_thread::get_id();unsigned n = std::thread::hardware_concurrency(); // approx # of hw threads, 0 if unknownstd::this_thread::sleep_for(std::chrono::milliseconds(100));thread_local int callCount = 0; // separate instance per thread
Key Facts
Behaviors that trip up new std::thread users.
- Non-copyable- std::thread objects can be moved but not copied; ownership of the OS thread transfers on move.
- Uncaught destructor- If a joinable std::thread is destroyed without join() or detach() being called, std::terminate() is invoked.
- Arguments are copied by default- Even if the target function takes a reference, arguments are copied unless wrapped in std::ref/std::cref.
- Exceptions don't cross threads automatically- An uncaught exception in a thread function calls std::terminate(); propagate results via std::promise/std::future instead.
- std::jthread (C++20)- Auto-joins on destruction and supports cooperative cancellation via std::stop_token.
Pro Tip
Prefer std::jthread (C++20) over std::thread when available - it automatically joins in its destructor, eliminating the classic bug where an exception or early return skips a manual join() and crashes the program via std::terminate.
Was this cheat sheet helpful?
Explore Topics
#CConcurrencyStdThread#CConcurrencyStdThreadCheatSheet#Programming#Intermediate#CreatingThreads#PassingArguments#JoinVsDetach#Thread#OOP#Databases#Concurrency#CheatSheet#SkillVeris
Advertisement
Sri Hayavadhana Info-Tech
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance