将输出流对象和其他参数传递给多个线程

时间:2017-04-13 19:23:01

标签: c++ multithreading c++11 ofstream

我正在尝试使用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 作为输入,那么一切正常:

oa << tree

通过这种方式,一切正常,它可以编译并且运行完美。但我真的不明白为什么编译器告诉我,如果我使用其他方法,我正在尝试使用已删除的复制构造函数。

感谢您的帮助。

1 个答案:

答案 0 :(得分: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数组在所有线程完成之前一直存在。

相关问题