2012-08-08 123 views
17

我很困惑void operator()()的功能。void operator的功能()()

你能告诉我有关,例如:

class background_task 
{ 
public: 

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

background_task f; 

std::thread my_thread(f); 

在这里,我们为什么需要operator()()?第一个和第二个()是什么意思?其实,我知道正常操作员的操作,但是这个操作员很混乱。

回答

17

第一个()是操作符的名称 - 它是在对象上使用()时调用的操作符。第二个()用于参数,其中没有。

这里是你如何使用它的一个例子:

background_task task; 
task(); // calls background_task::operator() 
+0

很酷,现在更清晰。 – 2012-08-08 03:34:18

+0

除了这个显式调用任务()以外,是否存在operator()()的隐式调用? – 2012-08-08 06:22:18

+1

@ forester2012,不,你必须总是明确地调用它,尽管你也可以使用更为尴尬的'task.operator()()'语法。有许多标准算法会在内部调用这个算子。 – 2012-08-08 13:10:20

21

可以重载()运营商打电话给你的对象,如果它是一个功能:

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

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

因此,第一个括号始终为空:这是函数的名称:operator(),第二个括号可能有参数(如我的示例中所示),但他们不必(如在您的示例中)。

因此,要在您的特定情况下调用此运算符,您可以执行类似task()的操作。

+0

很酷,你的解释让我现在清楚 – 2012-08-08 03:33:50

+0

operator()()只被调用没有任何参数?还有其他情况可以运行吗? – 2012-08-08 03:35:05

+1

@ forester2012,你可以通过在第二个'()'中声明参数来选择有多少个参数,如下所示。您也可以使用不同的参数列表声明不同的'operator()'函数,并且C++将根据您在调用时使用的参数选择正确的函数。 – 2012-08-08 03:36:31

6

第一部分operator()是声明当一个类的实例被调用为函数时调用的函数的方式。第二对括号将包含实际参数。

带有返回值和参数,这可能会使更多的意义:线程,即无论是内部

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)); 

在此背景下,std::thread将在内部调用f()内的operator()身体是什么鬼在该线程内完成。

1

以上贡献的所有提示对顺序程序都是正确的,我的意思是,程序没有线程。使用线程的东西改变。 首先,默认情况下,std :: thread的参数是函数和函数参数。也许你正在研究的书 “在行动C++并行”,作者显示了一个有趣的例子:

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

假设这个函数:

无效do_other_job(INT K); 在代码的身体,你应该做的:

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

为了产卵另一个线程。

因此,使用线程编译器会将f(在std :: thread my_thread(f);)中解释为函数而不是类。为了改变这种情况,你必须启动一个操作符()来警告编译器你正在使用一个类。 另一种代码可能是:

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

最终,它是不正确的,使用线程,饲养操作,所以这段代码不起作用:

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

这是因为里面的所有代码括号是只读的,在运行期间不能更改。如果您的目标是在构造函数中插入一个变量,它必须放入线程初始化中。所以:

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

将运行无误,并且将执行催生线程功能do_sth(12)。

我希望我能帮上忙。