2012-08-08 12 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()()を必要とする理由?第1と第2の意味は何ですか?()?実際、私は通常のオペレータの操作を知っていますが、このオペレータは混乱しています。

答えて

17

最初の()は演算子の名前です。これは、オブジェクトに()を使用したときに呼び出される演算子です。 2番目の()はパラメータのためのもので、そのうちのものはありません。ここで

は、あなたがそれを使用する方法の例です:

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

クールで、より明確になりました。 –

+0

この明示的なコールタスク()を除いて、operator()()の暗黙的な呼び出しはありますか? –

+1

@ forester2012、あなたはもっとはるかに扱いにくい 'task.operator()()'構文も使うことができますが、常に明示的に呼び出さなければなりません。この演算子を内部的に呼び出す多くの標準アルゴリズムがあります。 –

21

あなたはそれが機能したかのように、あなたのオブジェクトを呼び出すために()演算子をオーバーロードすることができます

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

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

だから、最初の括弧はされています常に空です:これは関数の名前です:operator()、2番目のかっこにはパラメータがありますが(例のように)必要はありません。

特定のケースでこの演算子を呼び出す場合は、task()のような処理を行います。

+0

cool、あなたの説明は今私にはっきりしています –

+0

operator()()はパラメータなしでのみ呼び出されますか?それを実行する他のケースはありますか? –

+1

@ forester2012では、ここに示すように、2番目の '()'の中にパラメータを宣言することで、いくつのパラメータがあるかを選択できます。異なるパラメータリストを持つ異なる 'operator()'関数を宣言してもよく、C++はそれを呼び出すときに使用するパラメータに基づいて正しいものを選択します。 –

6

最初の部分operator()は、クラスのインスタンスが関数として呼び出されたときに呼び出される関数を宣言する方法です。 2番目のカッコのペアには実際の引数が入ります。これはもう少し意味をなさない可能性がある戻り値と引数を持つ

:この文脈で

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)が実行されます。

私は助けてくれることを願っています。