Functionality of void operator()()

2019-03-11 05:57发布

I am confused about the functionality of void operator()().

Could you tell me about that, for instance:

class background_task
{
public:

    void operator()() const
    {
        do_something();
        do_something_else();
    }
};

background_task f;

std::thread my_thread(f);

Here, why we need operator()()? What is the meaning of the first and second ()? Actually, I know the operation of normal operator, but this operator is confusing.

标签: c++
4条回答
我命由我不由天
2楼-- · 2019-03-11 06:07

You can overload the () operator to call your object as if it was a function:

class A {
public:
    void operator()(int x, int y) {
        // Do something
    }
};

A x;
x(5, 3); // at this point operator () gets called

So the first parentheses are always empty: this is the name of the function: operator(), the second parentheses might have parameters (as in my example), but they don't have to (as in your example).

So to call this operator in your particular case you would do something like task().

查看更多
霸刀☆藐视天下
3楼-- · 2019-03-11 06:24

The first part operator() is the way to declare the function that is called when an instance of the class is invoked as a function. The second pair of parentheses would contain the actual arguments.

With a return value and arguments this might make a bit more sense:

class Adder{
public:
int operator()(int a, int b){
    //operator() -- this is the "name" of the operator
    //         in this case, it takes two integer arguments.
    return a+b;
}
};
Adder a;
assert( 5==a(2,3) );

In this context, the std::thread will internally invoke f() inside the thread, i.e. whatever is inside the body of operator() is what gets done inside that thread.

查看更多
Lonely孤独者°
4楼-- · 2019-03-11 06:24

All the hints that were contributed above are correct to sequential programs, I mean, programs without threads. Using threads things change. First of all, by default parameters to std::thread are functions and functions parameters. Probably you were studying the book "C++ concurrency in action", and the author shows an interesting example:

void do_some_work(); 
thread my_thread(do_some_work); //thread receives the function address

Suppose this function:

void do_other_job(int k); In the body of the code, you should do:

k=3; 
thread my_thread2(do_other_job, k); 

in order to spawn another thread.

So, using threads the compiler interprets f ( in std::thread my_thread(f);) by default as a function instead of a class. To change that you have to initiate an operator() to warn the compiler you are working with a class. An alternative code could be:

class background_task{
public: 
background_task(){
 do_sth(); 
 do_sth_else(); 
 }
void operator()(){} 
}; 
background_task f; 
thread mythread10(f);

Eventually, it's not correct, using threads, feeding the operator, so this code doesn't work:

void operator()(int x){
do_sth(); 
cout<<"x = "<<x<<endl;
}

It happens because all the code inside the brackets are read-only, and cannot be changed during the run-time. If you aim to insert a variable in the constructor, it must be put in the thread initialization. So:

class backg{
public: 
backg(int i){
   do_sth(i); 
   }
void operator()(){}
}; 
int main(){
thread mythread{ backg(12) }; //using c++11
return 0; 
}

Will run without mistakes, and will perform the function do_sth(12) in the thread spawned.

I hope I have helped.

查看更多
爱情/是我丢掉的垃圾
5楼-- · 2019-03-11 06:30

The first () is the name of the operator - it's the operator that is invoked when you use () on the object. The second () is for the parameters, of which there are none.

Here's an example of how you would use it:

background_task task;
task();  // calls background_task::operator()
查看更多
登录 后发表回答