使用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]; } }
注:构造函数可正常从二进制文件加载数据,无异常。
遇到的问题
- 尝试在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])); }
目前已通过在循环内绑定解决此问题,但想明确出错原因。
- 将
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
相关产品推荐
相关产品推荐

