2015-11-24 123 views
1

這次我遇到std::thread &的另一個問題,同時應用std::move來交換2個值。我的代碼說: -在std :: thread中使用std :: move

#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你打電話

拷貝/移動所有參數(函數對象f和所有 ARGS都...),以線程訪問的存儲,就好像由函數:

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

而且std::decay將刪除cv修飾符,其包括r值的引用。

因此,當std::thread是複製/移動參數來線程訪問的存儲,它本質上是移動構建它自己從您提供的那些int秒,因爲一個int一個move是一個簡單的複製,當您執行swapno對它的價值,你在拷貝。

要糾正它,使用std::refswap

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

Live Demo

+0

因此根據你的說法,我們不能在'threads'中使用'rvalue references'? –

+1

@AnkitAcharya:不完全。之後您想要訪問數據時,不應使用右值引用。在你的情況下,int上的'std :: move'是無用的,但如果你想讓線程自己的'vector '來處理(你在主線程中構建的),那麼'std :: move ''''矢量'是有用的。 – AndyG

0

通俗地說,線程的構造函數接受的臨時/右值傳遞給函數的參數。因此,你必須用一個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; 
}