7

forループ内にラムダがあり、ラムダにループ変数パラメーターがあります。実行すると、0〜9の数字が出力されると思います。ただし、ラムダであるため、xはすぐには評価されません。

    for( int x = 0; x < n; ++x)
    {
            vec.push_back(thread{[&x](){
                    m.lock();
                    cout << x << endl;
                    m.unlock();
            }});
    }

出力:

0
3
3
9

他の言語の解決策は、一時変数を作成することです。

    for( int x = 0; x < n; ++x)
    {
            int tmp = x;
            vec.push_back(thread{[&tmp](){
                    m.lock();
                    cout << tmp << endl;
                    m.unlock();
            }});
    }

しかし、それはうまくいかないようです。

間違ったパラメータを受け取るスレッドを参照してください

ボーナス:

答えを探しているときに 、イテレータを無効にするコンテナを使用しないことを推奨するラムダで動作するようにC ++11スレッドクラスを一般化するというこの質問に出くわしました。なぜだろう/

4

3 に答える 3

13

キャプチャを指定する場合、値によるキャプチャと参照によるキャプチャのどちらかを選択できます。参照によってキャプチャすることを選択しました。参照によるキャプチャとは、ラムダ関数内の変数が同じオブジェクトを参照していることを意味します。つまり、この変数への変更はすべて共有され、参照されるオブジェクトがラムダ関数の存続期間中存続することを確認する必要もあります。

あなたはおそらく価値観によって捕らえるつもりでした。これを行うには、キャプチャ仕様を置き換えるか、になる[=]かを指定し[x]ます。後者はx、前者が他の変数にアクセスできるようにする一方で、アクセスできることを確認します。

ところで、明示的に使用するのではなく、ロックガードの1つを使用することをお勧めします。これにより、ループの本体は次のようになります。lock()unlock()

vec.push_back(std::thread{[x](){
    std::lock_guard<std::mutex> kerberos(m);
    std::cout << x << "\n";
}});
于 2012-09-17T00:17:49.547 に答える
6

コピーを作成する場合は、参照ではなくでパラメータをキャプチャします。

vec.push_back(std::thread{[x](){
  m.lock();
  std::cout << x << std::endl;
  m.unlock();
}});

xこれにより、ラムダオブジェクトが作成されたときの値がコピーされます(スレッドが開始されたときではありません)。

答えを探しているときに、イテレータを無効にするコンテナを使用しないことを推奨するラムダで動作するようにC ++11スレッドクラスを一般化するというこの質問に出くわしました。なぜだろう/

これは、pthreadsライブラリを直接使用するまったく異なる実装について話しているためです。std::threadC++で動作するように設計されたを使用しています。

于 2012-09-17T00:09:13.223 に答える
3

問題は、参照によってxをキャプチャしていることです。したがって、各ループの終わりでxがインクリメントされると、それはスレッドに反映されます。

ラムダが作成されたときにラムダがxの値のみを使用するように、xを値でキャプチャする必要があります。

for( int x = 0; x < n; ++x)
{               
   vec.push_back(thread{[x](){
      m.lock();
      cout << tmp << endl;
      m.unlock();
   }});
}
于 2012-09-17T00:10:00.690 に答える