我正在尝试使用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
通过这种方式,一切正常,它可以编译并且运行完美。但我真的不明白为什么编译器告诉我,如果我使用其他方法,我正在尝试使用已删除的复制构造函数。
感谢您的帮助。
答案 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
数组在所有线程完成之前一直存在。