Home > Software design >  In C , How a std::thread can call a member function without creating an object?
In C , How a std::thread can call a member function without creating an object?

Time:02-17

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 
  • Related