You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用std::bind实现多线程:参数传递与结果存储异常问题

C++多线程数据处理问题解答

相关代码文件

process_data.h

void computeAvgFactor(const int*, int, int, double&);
void computeVarFactor(const int*, int, int, double, double&);
class ProcessData {
    int total_items{};
    int* data{};
    int num_threads{ 0 }; // 存储线程数量
    double* averages{ nullptr }; // 存储平均因子
    double* variances{ nullptr }; // 存储方差因子
    int* p_indices{ nullptr }; // 存储分区索引
public:
    ProcessData(std::string, int n_threads);
    ProcessData(const ProcessData&) = delete;
    ProcessData& operator=(const ProcessData&) = delete;
    ~ProcessData();
    int operator()(std::string, double&, double&);
};

process_data.cpp

void computeAvgFactor(const int* arr, int size, int divisor, double& avg)
{
    avg = 0;
    for (int i = 0; i < size; i++)
    {
        avg += arr[i];
    }
    avg /= divisor;
}

void computeVarFactor(const int* arr, int size, int divisor, double avg, double& var)
{
    var = 0;
    for (int i = 0; i < size; i++)
    {
        var += (arr[i] - avg) * (arr[i] - avg);
    }
    var /= divisor;
}

int ProcessData::operator()(std::string filename, double& avg, double& var)
{
    std::vector<std::thread> threads;
    int nParts = total_items / num_threads;

    for (int i = 0; i < num_threads;i++)
    {
        auto p = std::bind(computeAvgFactor, &data[p_indices[i]], nParts, total_items, averages[i]);
        threads.push_back(std::thread(p));
    }
    for (auto& thread : threads)
    {
        thread.join();
    }
    threads.clear();

    for (int i = 0; i < num_threads;i++)
    {
        avg += averages[i];
    }
}

注:构造函数可正常从二进制文件加载数据,无异常。

遇到的问题

  1. 尝试在for循环外使用占位符绑定computeAvgFactor时,触发C2893、C2672参数无效错误,代码示例:
auto p = std::bind(computeAvgFactor, _1, _2, &total_items, _3);

for (int i = 0; i < num_threads;i++)
{
    threads.push_back(std::thread(p, &data[p_indices[i]], nParts, averages[i]));
}

目前已通过在循环内绑定解决此问题,但想明确出错原因。

  1. 将averages[i]传入computeAvgFactor后,函数执行完毕averages[i]未保存计算结果。推测需要传引用,但使用&averages[i]时同样触发C2893、C2672错误,求解决办法。

问题解答

问题1:循环外绑定占位符出错的原因

  • 占位符_1、_2等属于std::placeholders命名空间,若代码未添加using namespace std::placeholders;或未完整指定std::placeholders::_1,编译器无法识别占位符,会抛出参数无效的错误。
  • computeAvgFactor的第三个参数是int类型,但你传递了&total_items(int*类型),类型不匹配,这也是触发错误的关键原因。

问题2:averages[i]无法保存结果的解决方法

computeAvgFactor的第四个参数是double&(引用类型),但std::bind默认会拷贝实参,导致函数内部操作的是临时拷贝对象,而非原数组元素。要传递引用,必须用std::ref()包裹averages[i],让std::bind传递引用而非拷贝。

修改循环内的绑定代码即可解决:

auto p = std::bind(computeAvgFactor, &data[p_indices[i]], nParts, total_items, std::ref(averages[i]));

如果要实现循环外绑定(修正问题1的正确写法),需要补充命名空间并修正参数类型:

// 引入占位符命名空间
using namespace std::placeholders;

// 正确绑定:第三个参数传int类型的total_items,第四个参数用占位符_3
auto p = std::bind(computeAvgFactor, _1, _2, total_items, _3);

for (int i = 0; i < num_threads;i++)
{
    // 传递averages[i]的引用
    threads.push_back(std::thread(p, &data[p_indices[i]], nParts, std::ref(averages[i])));
}

内容的提问来源于stack exchange,提问作者OldSchool Ty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 12:24:19