为什么std :: move不能与std :: list一起使用

时间:2017-07-04 17:30:00

标签: c++ c++11 stl

我无法编译以下程序。

void toSin(std::list<double>&& list)
{
    std::for_each(list.begin(), list.end(), [](double& x)
    {
        x = sin(x);
    });
}

int main()
{
    std::list<double> list;
    const double pi = 3.141592;
    const double epsilon = 0.0000001;
    for (double x = 0.0; x < 2 * pi + epsilon; x = x + pi / 16)
    {
        list.push_back(x);
    }
    // Start thread
    std::thread th(toSin, std::move(list));
    th.join();
    return 0;
}

我得到&gt;错误C2664:“void (std::list<double,std::allocator<_Ty>> &&)”:无法将参数1从“std::list<double,std::allocator<_Ty>>”转换为“std::list<double,std::allocator<_Ty>> &&

2 个答案:

答案 0 :(得分:0)

我觉得你的编译器错了。衰减(复制)值类型应该可绑定到右值引用。

无论如何看看this quote from the documentation

  

3)创建新的std :: thread对象并将其与执行线程相关联。新的执行线程开始执行

std::invoke(decay_copy(std::forward<Function>(f)), decay_copy(std::forward<Args>(args))...);

基本上,作为参数传递给std::thread的构造函数的任何内容都将作为函数参数复制到函数中。

另外要知道,如果您按函数而不是通过右值引用接受std::list变量,那么您的函数将正常工作。有关详情,请参阅Correct usage of rvalue references as parameters

如果你的意图是将对变量的引用传递给线程函数,那么我的方式通常是使用lambda

std::list<double> lst;
auto th = std::thread{[&lst]() {
    toSin(lst);
}};

但您也可以使用std::ref获得相同的效果。我个人觉得lambda方法更清晰。

std::list<double> lst;
auto th = std::thread{toSin, std::ref(lst)};

Also as correctly pointed out in the comments,您的代码中存在竞争条件,您应该使用mutex阻止,或等待线程完成

auto th = std::thread{[&lst]() {
    toSin(lst);
}};
th.join();

// then iterate and print out

答案 1 :(得分:0)

我认为您可能会错过一些#include,该代码适用于Visual Studio 2015

#include <algorithm>
#include <list>
#include <thread>
void toSin(std::list<double>&& list)
{
    std::for_each(list.begin(), list.end(), [](double& x)
    {
        x = sin(x);
    });
}

int main()
{
    std::list<double> list;
    const double pi = 3.141592;
    const double epsilon = 0.0000001;
    for (double x = 0.0; x < 2 * pi + epsilon; x = x + pi / 16)
    {
        list.push_back(x);
    }
    // Start thread
    std::thread th(toSin, std::move(list));
    th.join();
    return 0;
}