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

标签 c++ multithreading c++11 ofstream

我正在尝试使用 C++11 标准将多个参数(其中一个是 ofstream 对象)传递给多个线程。

我想传递一个 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

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

感谢您的帮助。

最佳答案

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数组会一直存在,直到您的所有线程都完成它。

关于c++ - 将输出流对象和其他参数传递给多个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43400190/

相关文章:

c++ - 在 C++ 中替代 bash 同步

c++ - 不明白这个C++方法是如何工作的,想做类似的事情

C CLI 游戏概念

c++ - ia 是数组时无法推断出 "auto ia2(ia)"

ios - 保存在其他线程中时,应用崩溃

java - 停止 JUnit 完成,直到所有其他线程都已停止

c++ - 要使用的类初始化括号

c++ - 动态分配

c++ - 为什么 static_cast 对表达式进行分配?

c++ - 类的析构函数中的访问冲突读取位置