简体   繁体   English

在std :: thread中使用std :: move

[英]using std::move in std::thread

I encountered yet another problem with std::thread & this time while applying std::move to swap 2 values. 我在使用std::move到swap 2值时遇到了std::thread另一个问题。 My code says :- 我的代码说: -

#include <iostream>
#include <thread>
using namespace std;
void swapno (int &&a, int &&b)
{
    int temp=move(a);
    a=move(b);
    b=move(temp);
}
int main()
{
    int x=5, y=7;
    cout << "x = " << x << "\ty = " << y << "\n";
//  swapno (move(x), move(y));  // this works fine
    thread t (swapno, move(x), move(y));
    t.join();
    cout << "x = " << x << "\ty = " << y << "\n";
    return 0;
}

Output :- 输出: -

x = 5   y = 7
x = 5   y = 7

Now what's wrong in this method ? 现在这个方法有什么问题? Why is such the code showing such a behaviour ? 为什么这样的代码显示出这样的行为? How do I correct it ? 我该如何纠正?

It's because the thread constructor you're calling 这是因为你正在调用的thread 构造函数

copies/moves all arguments (both the function object f and all args...) to thread-accessible storage as if by the function: 将所有参数(包括函数对象f和所有参数...)复制/移动到线程可访问的存储,就像通过函数一样:

template <class T>
typename decay<T>::type decay_copy(T&& v) {
    return std::forward<T>(v);
}

And std::decay will remove cv-qualifiers, which includes r-value references. 并且std::decay将删除cv-qualifiers,其中包括r值引用。

Thus, when std::thread is copy/moving arguments to thread-accessible storage, it's essentially move constructing it's own int s from the ones you provided, and because a move on an int is simply a copy, when you perform swapno on its values, you're doing it on copies. 因此,当std::thread是复制/移动参数到线程可访问的存储时,它本质上是从你提供的那些移动构造它自己的 int ,并且因为int上的move只是一个副本,当你swapno执行swapno时价值观,你是在副本上做的。

To correct it, use std::ref plus swap : 要更正它,请使用std::ref plus swap

std::thread t ([](int& a, int& b){std::swap(a, b);}, std::ref(x), std::ref(y));
t.join();

Live Demo 现场演示

In layman's terms, thread's constructor accepts temporaries/rvalues to the arguments passed to the function. 通俗地说,线程的构造函数接受传递给函数的参数的temporaries / rvalues。 Therefore you have to wrap it with a reference_wrapper, which is a value but wraps the underlying reference (what std::ref does). 因此,您必须使用reference_wrapper包装它,这是一个值但包装底层引用(std :: ref的作用)。

The code below does the trick with std::swap out of the box. 下面的代码使用std :: swap开箱即用。 Using std::swap as argument to thread (or std::function) causes and ambiguous overload (which surprised me too). 使用std :: swap作为thread(或std :: function)的参数导致和模糊的重载(这也让我感到惊讶)。

int main(int argc, char* argv[])
{
  int x = 5, y = 7;
  std::cout << "x(" << x << ")" << " y(" << y <<")" << std::endl;
  void (*pf)(int& x, int& y) = std::swap<int>;
  std::thread t1(pf, std::ref<int>(x), std::ref<int>(y));
  t1.join();
  std::cout << "x(" << x << ")" << " y(" << y <<")" << std::endl;
  return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM