如何将接收引用参数的函数传递给C++ std::thread线程?
编译失败原因
std::thread 构造函数默认会对传入的所有参数执行复制/移动构造,存储到线程内部的参数列表中,后续传递给目标函数时参数是作为右值传递的,无法绑定到函数要求的非常量左值引用(int&)上,因此触发编译错误。另外你代码中add函数的第二个形参是int& b,直接传入字面量2、5同样会因为右值无法绑定到非常量左值引用报错,可根据需求改为const int&或者传入变量。
替代解决方案
除了使用vector之外,还有3种常用的可行方案,均适配数组指针类参数的传递需求:
方案1:用
std::ref显式标记引用参数
这是C++标准推荐的传引用给线程的方式,用std::ref包装需要按引用传递的参数,告诉std::thread不要复制该参数,保留其引用属性。
修正后示例代码:#include <thread> #include <iostream> #include <functional> // std::ref 所需头文件 // 无需修改的参数建议加const限定,支持直接传入字面量 void add(int a, const int& b, int c, int& acc) { acc += a + b + c; } int main() { int acc = 0; // 用std::ref包装需要按引用传递的acc std::thread t1(add, 1, 2, 3, std::ref(acc)); std::thread t2(add, 4, 5, 6, std::ref(acc)); t1.join(); t2.join(); // 输出结果为21(1+2+3 + 4+5+6) std::cout << acc; return 0; }传递数组引用时,同样用
std::ref包装数组变量即可。方案2:用lambda表达式包装目标函数
自己通过lambda控制参数的捕获和传递逻辑,不需要依赖std::thread的参数转发机制,灵活度更高,处理数组指针、复杂参数时更方便。
示例代码:int main() { int acc = 0; // 按引用捕获acc,直接在lambda内部调用add函数 std::thread t1([&acc](){ add(1, 2, 3, acc); }); std::thread t2([&acc](){ add(4, 5, 6, acc); }); t1.join(); t2.join(); std::cout << acc; return 0; }方案3:用指针替代引用传递参数
将需要修改的参数改为指针类型,std::thread传递时只会复制指针本身,指向的内存地址和原变量一致,也可以实现修改原变量的效果,天然适配数组指针的传递需求。
示例代码:// 将acc参数改为指针类型 void add(int a, const int& b, int c, int* acc) { *acc += a + b + c; } int main() { int acc = 0; // 直接传入acc的地址即可 std::thread t1(add, 1, 2, 3, &acc); std::thread t2(add, 4, 5, 6, &acc); t1.join(); t2.join(); std::cout << acc; return 0; }
注意事项
示例代码中两个线程同时修改acc变量存在数据竞争,实际生产环境使用时需要加std::mutex互斥锁,或者将acc改为std::atomic<int>类型,避免出现未定义行为。
内容的提问来源于stack exchange,提问作者Wais Kamal
相关产品推荐
相关产品推荐

