#include <iostream>
#include <thread>
template<int Num>
class MyClass {
public:
MyClass(int val) : val_(val) {}
// Copy constructor
MyClass(const MyClass& other) : val_(other.val_) {
std::cout << "Copy constructor called" << std::endl;
}
// Move constructor
MyClass(MyClass&& other) noexcept : val_(other.val_) {
std::cout << "Move constructor called" << std::endl;
}
private:
int val_;
};
template<int Num>
void threadFunction(MyClass<Num> myObj) {
std::cout << "Inside thread" << std::endl;
}
int main() {
MyClass<1> obj(42);
std::thread t1(threadFunction<1>, obj); // <-- pass by value
std::thread t2(threadFunction<1>, std::ref(obj)); // <-- pass by reference
t1.join();
t2.join();
return 0;
}
I want to pass an object by value to a thread to ensure each thread works on its own copy (thread t1
).
When I create thread t2
, I pass the object by reference using std::ref(obj)
.
Clearly, my intention per function definition is to pass the object by value rather than by reference. Is obj a shared variable if passed as std::ref(obj)
among all threads?
This question std::ref using with template function and function passing by value seems to address a similar topic, but not in multithreading context. In the example shown there, there seems to be a difference if the function is templated.
EDIT 1:
I added a copy and move constructor to the class motivated by the discussion in the answer below.
Why would it not compile?
std::ref
returns a std::reference_wrapper
which has an implicit conversion to reference to stored object that is used here.
Is obj a shared variable if passed as
std::ref(obj)
among all threads?
No. Each thread gets a copy.
The situation is similar to
void foo( int a) { std::cout << a; }
int main() {
int x = 42;
int& ref = x;
foo(ref);
}
ref
is a reference to x
. When you call foo(ref)
then a
is a copy of x
.
Actually the need to use std::ref
arises because the thread constructor always gets its parameters by value. And if the function called by the thread is template <typename Num> void threadFunction(MyClass<Num> myObj)
, ie it accepts a value, then nothing can magically change it to get myObj
passed by reference.