简体   繁体   English

使用线程 class 在 C++ 中构造动态线程数组时出错

[英]Error with constructing a dynamic array of threads in C++, using the thread class

As a part of a uni project I have to create a program which can have an arbitrary amount of threads given as a command line argument.作为 uni 项目的一部分,我必须创建一个程序,该程序可以将任意数量的线程作为命令行参数给出。 I first tried making a dynamic array of threads like this: thread* threads = new thread[numThreads];我首先尝试制作这样一个动态线程数组: thread* threads = new thread[numThreads]; ( Note: I want to use the threads class, not pthreads ). (注意:我想使用线程 class,而不是 pthreads)。 I figured it didn't work because to my knowledge new tries to call default constructors to thread, which it doesn't have and lator on I cannot actually construct the threads properly.我认为它不起作用,因为据我所知 new 尝试将默认构造函数调用到线程,它没有,并且我实际上无法正确构造线程。 Then I tried to do it in the following way:然后我尝试通过以下方式进行操作:

thread** threads = new thread*[numThreads];
for (int i = 0; i < numThreads; i++)
    {
        threads[i] = new thread(calculateFractal, width, height, numThreads, i, fractal, xmin, xmax, ymin, ymax, xStepSize, yStepSize, maxNorm);
    }

I have defined the function and all of the used variables in the aforementioned constructors in the for are of their appropriate data types:我已经定义了 function 并且在 for 中上述构造函数中使用的所有变量都是它们适当的数据类型:

void calculateFractal(int& width, int& height, int& numThreads, int& thisThreadNum, RGB**& fractal, 
    long double& xmin, long double& xmax,long double& ymin, long double& ymax,
    long double& xStepSize, long double& yStepSize, long double& maxNorm)

This code still doesn't work and gives the same compiler errors( C2672 and C2893 ) for essentially inappropriate function template as if I have not passed the correct type of arguments.此代码仍然不起作用,并且对于本质上不适当的 function 模板给出相同的编译器错误( C2672C2893 ),就好像我没有通过正确类型的 arguments 一样。 Can you figure out what is wrong with the code?你能弄清楚代码有什么问题吗?

Use std::vector<std::thread> , as follows使用std::vector<std::thread> ,如下

std::vector<std::thread> threadsVec(threadsNumber);
for(size_t i{}; i < threadsNumber; ++i){
    threadsVec[i] = std::thread{.....};
}

and when you put the args make sure you use std::ref(arg) when your function need a reference because std::thread takes rvalues only, hence you have to introduce an std::reference_wrapper并且当您放置 args 时,请确保在您的 function 需要引用时使用std::ref(arg) ,因为std::thread仅采用rvalues ,因此您必须引入std::reference_wrapper

The following is a complete working example以下是一个完整的工作示例

#include <thread>
#include <iostream>
#include <vector>

struct RGB{};

void calculateFractal(int& width, int& height, int& numThreads, int& thisThreadNum, RGB**& fractal,
                      long double& xmin, long double& xmax,long double& ymin, long double& ymax,
                      long double& xStepSize, long double& yStepSize, long double& maxNorm){
    std::cout << "inside the thread";
}
int main()
{
    int width, height, thisThreadNum;
    RGB fractal1;
    RGB* fractal2 = &fractal1;
    RGB** fractal3 = &fractal2;
    long double xmin, xmax, ymin, ymax, xStepSize, yStepSize, maxNorm;

    int threadsNumber = 1;
    std::vector<std::thread> threadsVec(threadsNumber);
    for(size_t i{}; i < threadsNumber; ++i){
        threadsVec[i] = std::thread{calculateFractal, std::ref(width), std::ref(height),
                        std::ref(threadsNumber), std::ref(thisThreadNum), std::ref(fractal3),
                        std::ref(xmin), std::ref(xmax), std::ref(ymin), std::ref(ymax),
                        std::ref(xStepSize), std::ref(yStepSize), std::ref(maxNorm)
        };
    }


    for(size_t i{}; i < threadsNumber; ++i){
        threadsVec[i].join();
    }

}

Use std::vector instead of C-style arrays.使用std::vector代替 C 风格的 arrays。 You need to use std::ref for the reference parameters, as std::thread otherwise doesn't know to pass them by reference:您需要使用std::ref作为引用参数,因为std::thread否则不知道通过引用传递它们:

std::vector<std::thread> threads;
threads.reserve(numThreads);
for (int i = 0; i < numThreads; i++) {
  threads.emplace_back(calculateFractal, std::ref(width), std::ref(height), std::ref(numThreads), i, std::ref(fractal),
    std::ref(xmin), std::ref(xmax), std::ref(ymin), std::ref(ymax), std::ref(xStepSize), std::ref(yStepSize), std::ref(maxNorm));
}

This allows you to store the threads efficiently in an array-like structure, while still being able to construct them one-by-one.这使您可以将线程有效地存储在类似数组的结构中,同时仍然能够一个接一个地构造它们。

You pass i as a reference, as the parameter is defined as int& thisThreadNum .您将i作为参考传递,因为参数定义为int& thisThreadNum That means all threads will try to access the i variable, possibly after it as been modified, or even when it doesn't exist anymore, when the loop has terminated.这意味着所有线程都将尝试访问i变量,可能在它被修改之后,或者即使它不再存在,当循环终止时。 You have to remove the & to pass it by value (and not use std::ref on it), so that each thread gets its own copy containing the individual value.您必须删除&以按值传递它(而不是在其上使用std::ref ),以便每个线程都有自己的包含单个值的副本。

If that still doesn't work, please update the question with the exact error message, show the new code including the definition of all the variables, and whether calculateFractal is a class member function.如果这仍然不起作用,请使用确切的错误消息更新问题,显示新代码,包括所有变量的定义,以及calculateFractal是否是 class 成员 function。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM