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
