2015-11-24 3 views
1

У меня возникла еще одна проблема с std::thread & на этот раз при применении std::move для обмена 2 значениями. Мой код говорит: -using std :: move in std :: thread

#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 

Теперь то, что случилось в этом методе? Почему такой код показывает такое поведение? Как это исправить?

+0

Нить использует копию 'x' и' y', а не ссылку на них. Вместо этого вы можете передать указатель на 'x' и' y'. – Jerome

+0

Причины такие же, как и в предыдущем вопросе. Также используйте 'std :: swap'. – juanchopanza

+1

как вы перешли от "[вы должны обернуть его в std :: ref] (http://stackoverflow.com/a/33895159)" для использования &&? – Default

ответ

3

Это потому, что threadconstructor вы звоните

копий/перемещает все аргументы (как объект функции п и все арг ...) на поточно-доступную память, как если бы с помощью функции:

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

И std::decay удалит CV-классификаторы, которая включает в себя ссылку на г-значение.

Таким образом, когда std::thread копирования/перемещения аргументы в поточно-доступную память, она по существу двигаться построения его собственнойint s от тех, предоставленных вами, и потому move на int является просто копией, при выполнении swapno по своим значениям, вы делаете это на копиях.

Чтобы исправить это, используйте std::ref плюс swap:

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

Live Demo

+0

, поэтому, согласно вам, мы не можем использовать 'rvalue references' с' threads'? –

+1

@AnkitAcharya: Не совсем. Вы не должны использовать ссылки rvalue, когда хотите получить доступ к данным впоследствии. В вашем случае 'std :: move' в int бесполезен, но если вы хотите, чтобы поток дал свой собственный вектор vector ', над которым вы работаете (который вы создали в основном потоке), тогда 'std :: move '' ing, что 'vector' полезен. – AndyG

0

С точки зрения непрофессионала, конструктор потока принимает/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; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^