Pass multiple arguments into stdthread
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
std::thread in C++ accepts a callable (function, lambda, or functor) followed by any number of arguments that get forwarded to it. To pass multiple arguments, list them after the callable: std::thread(func, arg1, arg2, arg3). Arguments are copied by default. To pass by reference, wrap the argument in std::ref(). To pass a member function, provide a pointer to the member function followed by the object pointer and the remaining arguments. Understanding these mechanics is essential for avoiding dangling references, data races, and compilation errors in multithreaded C++ code.
Basic Multiple Arguments
Arguments are forwarded by value — std::thread copies each argument into internal storage. The function receives copies, not the original variables.
Passing by Reference with std::ref
By default, std::thread copies all arguments. To pass by reference, use std::ref():
Why std::ref is Needed
std::thread internally uses std::decay to remove references from argument types, then stores copies. std::ref() wraps the variable in a std::reference_wrapper that is copyable but dereferences to the original object.
Member Functions
To call a member function on a thread, pass a pointer to the member function, followed by the object (pointer or reference), then the remaining arguments:
Lambda Expressions
Lambdas are the most flexible way to pass multiple arguments, since captures handle references naturally:
Move-Only Types
Types like std::unique_ptr cannot be copied but can be moved into a thread:
Functors (Function Objects)
Common Pitfalls
- Forgetting
std::ref()for reference parameters:std::threadcopies all arguments by default. Passing a variable to a function expecting a reference compiles (the copy binds to the reference) but the original variable is not modified. Usestd::ref()when you need the thread to modify the caller's data. - Dangling references from local variables: If you pass a reference to a local variable using
std::ref()and the thread outlives the scope, the reference dangles. Ensure the referenced variable's lifetime extends pastthread.join(). - Forgetting to call
join()ordetach(): If astd::threadobject is destroyed while still joinable,std::terminate()is called. Always calljoin()(to wait) ordetach()(to let it run independently) before the thread object goes out of scope. - Passing string literals to
std::stringparameters:std::thread(func, "hello")copies theconst char*pointer, then constructs thestd::stringinside the thread. If the calling thread exits before construction, the pointer may dangle. Passstd::string("hello")explicitly to ensure the string is copied immediately. - Data races when multiple threads share references: Passing the same variable via
std::ref()to multiple threads without synchronization (mutex, atomic) causes undefined behavior. Protect shared data withstd::mutexor usestd::atomicfor simple types.
Summary
- Pass multiple arguments after the callable:
std::thread(func, arg1, arg2, arg3) - Arguments are copied by default — use
std::ref()to pass by reference - For member functions, pass
&Class::method, then the object pointer, then additional arguments - Use
std::move()for move-only types likestd::unique_ptr - Lambdas with captures are the most flexible approach and avoid many argument-passing pitfalls

