2017-04-13 18 views
0

我試圖將多個參數(其中之一是ofstream對象)傳遞給使用C++11標準的多個線程。將輸出流對象和其他參數傳遞給多個線程

我想通過一個ofstream對象,因爲我希望每個線程寫入不同的輸出文件。

我初始化線程和輸出流以這樣的方式

std::thread execution_threads[NUMBER_OF_THREADS]; // creating multiple empty threads 
std::ofstream output_files[NUMBER_OF_THREADS]; // Empty output streams 
// Opening and initializing the output files 

每個線程執行的函數有兩個參數:

void execution(int thread_id, std::ofstream& output_file) 

所以我環顧四周,我」已經閱讀C++11當函數func有多個參數a,b,c,d時,不需要使用struct,只需編寫std::thread t(func, a,b,c,d);就可以傳遞它們。所以,我爲了啓動線程寫這個循環:

for (int i = 0; i < utils::NUMBER_OF_THREADS; i++) { 
    execution_threads[i] = std::thread(execution, i, output_files[i]); 
} 

的事情是,這個代碼不與此錯誤編譯:

Call to implicitly-deleted copy constructor of 
'typename decay<basic_ofstream<char, char_traits<char> > &>::type' 
(aka 'std::__1::basic_ofstream<char, std::__1::char_traits<char> >') 

而如果我在使用struct作爲輸入方式,一切工作正常:

// Struct definition 
struct thread_input { 
    int thread_id; 
    std::ofstream& output_file; 
}; 

// This is the function that now has only one argument 
void execution(struct thread_input input) 

// And this is the loop that launches the threads 
for (int i = 0; i < utils::NUMBER_OF_THREADS; i++) { 
    struct thread_input input = {i, output_files[i]}; 
    execution_threads[i] = std::thread(execution, input); 
} 

// join() functions for each thread and end of the program 

這樣一切工作正常,它編譯和它運行完美。但我真的不知道爲什麼編譯器告訴我,如果我使用另一種方法,我正嘗試使用已刪除的副本構造函數。

謝謝你的幫助。

回答

2

std::thread存儲其參數的副本。當你通過一個不可複製的對象,如std::ofstream它會抱怨。

你有兩個選擇:

1)不要存放std::ofstream對象的數組;只是讓你的線程存儲自己的流。在這種情況下,沒有必要複製流(剛剛一動,這是很好的):

for (int i = 0; i < utils::NUMBER_OF_THREADS; i++) { 
    execution_threads[i] = std::thread(execution, i, std::ofstream{}); 
                //^^^^^^^^^^^^^^^ anonymous temporary 
} 

當然,在這種情況下,你可以只是線程構建其自己的流(也許只是傳中,文件名)。

2)將std::reference_wrapper<std::ofstream>通過您的線程。 std::reference_wrapper<T>是一個對象,它保存對T的引用,並將其隱式轉換爲T&,因此您只需複製引用而不是流本身。您可以使用std::ref工廠推斷T和減少輸入:

for (int i = 0; i < utils::NUMBER_OF_THREADS; i++) { 
    execution_threads[i] = std::thread(execution, i, std::ref(output_files[i])); 
                //^^^^^^^^ std::ref added 
} 

這使你所有這一切使包含有std::ofstream&將有一個結構相同的所有權和壽命的問題(畢竟,這是所有std::reference_wrapper是) 。您需要確保您的output_files陣列能夠存活,直到您的所有線程都完成爲止。