在 std::thread 中使用 std::move
using std::move in std::thread
我遇到了 std::thread
的另一个问题,这一次是在应用 std::move
交换 2 个值时。我的代码说:-
#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;
}
输出:-
x = 5 y = 7
x = 5 y = 7
现在这个方法有什么问题?为什么这样的代码显示出这样的行为?我该如何更正它?
这是因为 thread
constructor 你正在呼叫
copies/moves all arguments (both the function object f and all
args...) to thread-accessible storage as if by the function:
template <class T>
typename decay<T>::type decay_copy(T&& v) {
return std::forward<T>(v);
}
并且 std::decay
将删除 cv 限定符,其中包括 r 值引用。
因此,当 std::thread
是线程可访问存储的 copy/moving 个参数时,它本质上是从 它自己的 int
您提供的那些,并且因为 int
上的 move
只是一个副本,所以当您对其值执行 swapno
时,您是在副本上执行此操作。
要更正它,请使用 std::ref
加上 swap
:
std::thread t ([](int& a, int& b){std::swap(a, b);}, std::ref(x), std::ref(y));
t.join();
通俗地说,线程的构造函数接受 temporaries/rvalues 传递给函数的参数。因此,您必须用 reference_wrapper 包装它,这是一个值,但包装了底层引用(std::ref 所做的)。
下面的代码可以立即使用 std::swap。使用 std::swap 作为线程(或 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;
}
我遇到了 std::thread
的另一个问题,这一次是在应用 std::move
交换 2 个值时。我的代码说:-
#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;
}
输出:-
x = 5 y = 7
x = 5 y = 7
现在这个方法有什么问题?为什么这样的代码显示出这样的行为?我该如何更正它?
这是因为 thread
constructor 你正在呼叫
copies/moves all arguments (both the function object f and all args...) to thread-accessible storage as if by the function:
template <class T>
typename decay<T>::type decay_copy(T&& v) {
return std::forward<T>(v);
}
并且 std::decay
将删除 cv 限定符,其中包括 r 值引用。
因此,当 std::thread
是线程可访问存储的 copy/moving 个参数时,它本质上是从 它自己的 int
您提供的那些,并且因为 int
上的 move
只是一个副本,所以当您对其值执行 swapno
时,您是在副本上执行此操作。
要更正它,请使用 std::ref
加上 swap
:
std::thread t ([](int& a, int& b){std::swap(a, b);}, std::ref(x), std::ref(y));
t.join();
通俗地说,线程的构造函数接受 temporaries/rvalues 传递给函数的参数。因此,您必须用 reference_wrapper 包装它,这是一个值,但包装了底层引用(std::ref 所做的)。
下面的代码可以立即使用 std::swap。使用 std::swap 作为线程(或 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;
}