c++ - std::threads 构造函数参数错误

标签 c++ multithreading templates c++11 move

<分区>

我不是一个优秀的 C++ 程序员,但目前正在使用 C++ 的一些功能来清理我的 C 代码中的脏部分。 g++ 编译器提示 threads[i] = thread(split, i, sums[i], from, to, f, nThreads);。请帮我找出问题所在。

//mjArray 只是一个简单的类,而不是 std::vector ,这对我来说太重了。

#include <cstdio>
#include <cmath>
#include <ctime>
#include <thread>
using namespace std;

template<typename T>
class mjArray {
private:
    T* _array;
    int _length;

public:
    mjArray(int length) {
        _array = new T[length];
        _length = length;
    }

    mjArray(int length, T val) {
        _array = new T[length];
        _length = length;
        for (int i = 0; i < length; ++i) {
            _array[i] = val;
        }
    }

    ~mjArray() {
        delete[] _array;
    }

    T& operator[](int i) {
        return _array[i];
    }

    int length() {
        return _length;
    }
};

void split(int n, double& sum, int from, int to, double (*f)(double), int nThreads) {
    for (int i = from + n; i <= to; i += nThreads) {
        sum += f(i);
    }
}

double sigma(int from, int to, double (*f)(double), int nThreads) {
    double sum = 0.0;
    mjArray<double> sums(nThreads, 0.0);
    mjArray<thread> threads(nThreads);
    for (int i = 0; i < nThreads; ++i) {
        threads[i] = thread(split, i, sums[i], from, to, f, nThreads);
    }
    for (int i = 0; i < nThreads; ++i) {
        threads[i].join();
        sum += sums[i];
    }
    return sum;
}

double f(double x) {
    return (4 / (8 * x + 1) - 2 / (8 * x + 4) - 1 / (8 * x + 5) - 1 / (8 * x + 6)) / pow(16, x);
}

int main(void) {
    for (int i = 1; i <= 4; ++i) {
        time_t start = clock();
        double pi = sigma(0, 1000000, f, i);
        time_t end = clock();
        printf("pi = %.10f; nThreads = %d; elapsed = %.3fs\n", pi, i, (double)(end - start) / CLOCKS_PER_SEC);
    }
    return 0;
}

最佳答案

#include <functional>

threads[i] = thread(split, i, std::ref(sums[i]), from, to, f, nThreads);
//                            ~~~~~~~~^

理由:

std::thread 存储传递给其构造函数的参数的衰减拷贝,然后是 std::move d 初始化在该新线程中运行的仿函数对象的参数。在引用的情况下,这会失败,因为您无法使用 xvalue 初始化非常量左值引用(double& 您的 split 函数期望的)(更不用说它是一个完全不同的 double 实例与那个你传递给了 thread's 构造函数)。

解决方案是使用 std::reference_wrapper<T> 从辅助函数返回 std::ref 将您的引用包装在一个可复制对象中,该对象成功地将您的引用传输到新创建的线程。

关于c++ - std::threads 构造函数参数错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27532785/

相关文章:

c++ - 哪个Qt库包含QApplication

c# - 跨线程的 CollectionChanged 通知?

c++ - 检查类型是否为模板特化

c++ - 模板类型的重载决策和运算符 << 的问题 - 第 2 部分

templates - {{template "base"}} 和 {{template "base".}} 在 go-gin 中的区别

基于 C++ 策略的设计

c++ - 将 RGB 转换为十六进制 C++?

c++ - 创建文件 COM 端口错误 2

c - 线程变化的开始已经设置了全局变量

java - ConcurrentHashMap 上的同步