10

プログラムを終了する準備ができるまでループに入れておきたいスレッドがあります。プログラムを終了する準備ができたら、ループから抜け出して終了し、それを呼び出すことができるようstd::thread::joinにします。C++03 の時代には、スレッドにいつ終了するかを伝えるために、ロックで保護された bool を使用するだけでした。今回は新しいアトミック ライブラリ (具体的には ) を利用しようと思ったのですが、うまくいきませstd::atomic_boolん。以下は私のテストケースです:

#include <atomic>
#include <thread>
#include <cstdio>

using namespace std;

void setBool(atomic_bool& ab)
{
    ab = true;
}

int main()
{
    atomic_bool b;
    b = false;
    thread t(setBool, b);
    t.join();
    printf("Atomic bool value: %d\n", b.load());
    return 0;
}

コンパイルしようとすると、 の宣言はこの怪物をthread t吐き出します。エラーの中心部分は次のようです。

タイプ 'std::atomic_bool' の右辺値からのタイプ 'std::atomic_bool&' の非 const 参照の無効な初期化</p>

への参照を取得できないのはなぜatomic_boolですか? 代わりに何をすべきですか?

4

3 に答える 3

17

スレッドにrefを明示的に渡す必要があります。を使用すると、コピー可能なstd::refが作成され、関数への参照が伝達されます。std::reference_wrapper

thread t(setBool, std::ref(b));

それ以外の場合は、アトミックをコピーしようとしますが、これはコピーできません。

于 2012-10-27T19:58:37.080 に答える
7

Bamboon が説明したように、オブジェクトをの可変引数コンストラクターstd::refを介して参照渡ししたい場合は、オブジェクトを でラップする必要があります。std::thread(同じことが にも当てはまりますstd::async。) この直感に反する動作を回避するために、期待どおりに正確に動作するラムダを使用できます。これを使用してスレッドを作成するだけです:

thread t([&]{ setBool(b); });

ラムダを使用すると、参照によって引数を渡したいときに ref/cref のナンセンスは必要ありません。

于 2012-10-27T22:47:00.657 に答える
3

私もこれに遭遇しました。次のようにアドレスをアトミックに渡すことで問題を解決できると思います。

std::atomic<bool> b{false};
std::thread t(setBool, &b);

関数がアトミックへのポインターを取る場所:

void setBool(std::atomic<bool>* ab)

受け入れられている慣行が何であるかはわかりません。この方法でアトミックにヌルポインターを渡すことができると思いますが、なぜそうしたいのかわかりません。

于 2016-02-03T01:06:44.837 に答える