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&”类型的非常量引用无效</p>

为什么我无法获得对 a 的引用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

std::ref正如竹子解释的那样,如果你真的希望它们通过std::thread的变量参数构造函数通过引用传递,你必须包装对象。(同样适用于std::async。)为避免这种违反直觉的行为,您可以使用 lambda,它的行为与您预期的完全一样。只需使用它来创建线程:

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

使用 lambdas,当您想通过引用传递参数时,不需要 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 回答