If we have a class H
with some operator()
overloaded. How it is possible to create a thread from these member functions without instantiating an object from class H
. Consider the following code
#include<iostream>
#include<thread>
class H {
public:
void operator()(){
printf("This is H(), I take no argument\n");
}
void operator()(int x){
printf("This is H(), I received %d \n",x);
}
};
int main(){
int param = 0xD;
//No object created
std::thread td_1 = std::thread(H());
std::thread td_2 = std::thread(H(),param);
td_1.join();
td_2.join();
//From an object
H h;
std::thread td_3 = std::thread(h);
std::thread td_4 = std::thread(h,param);
td_3.join();
td_4.join();
return 0;
}
produce the output :
This is H(), I take no argument
This is H(), I received 13
This is H(), I take no argument
This is H(), I received 13
The question is, how td_1 and td_2 called the member function operator()
of class H
without an object of class H
?
CodePudding user response:
The syntax H()
is creating a temporary object of type H
in this context. The temporary object is passed to the std::thread
constructor.
Now, if the thread were to call operator()
on that temporary, that would be a problem, since the temporary will only live until the end of the line std::thread td_1 = std::thread(H());
and the thread function may execute after that.
However, the thread doesn't actually use that temporary. Instead a new object of the (decayed) argument type is created for the thread, copied/moved from the temporary object you gave to the constructor. This H
object lives until the thread exits and on this object operator()
is called.
CodePudding user response:
how td_1 and td_2 called the member function operator() of class H without an object of class H?
td_1
and td_2
does create objects of type H
. Those objects are temporaries. Next, those supplied function object(which are temporaries in this case) is moved/copied into the storage belonging to the newly created thread of execution and invoked from there.
You can confirm this by adding a default constructor and move constructor inside class H
as shown below:
#include<iostream>
#include<thread>
class H {
public:
void operator()(){
printf("This is H(), I take no argument\n");
}
void operator()(int x){
printf("This is H(), I received %d \n",x);
}
//default constructor
H()
{
std::cout<<"default constructor called"<<std::endl;
}
//move constructor
H(H&&)
{
std::cout<<"move constructor called"<<std::endl;
}
};
int main(){
int param = 0xD;
std::thread td_1 = std::thread(H());
std::thread td_2 = std::thread(H(),param);
td_1.join();
td_2.join();
return 0;
}
The output is:
default constructor called
move constructor called
move constructor called
default constructor called
move constructor called
move constructor called
This is H(), I take no argument
This is H(), I received 13