std::thread构造函数中按引用传递参数不生效问题
问题分析与解决方案
你碰到的这个问题是C++ std::thread 参数传递里的典型陷阱——哪怕你的函数参数声明是引用类型,std::thread 默认也会对传入的参数做值拷贝,而非传递原始变量的引用。
具体来说,当你写 thread pre_process_thread(process_data, parsed_data); 时,std::thread 会把 parsed_data 复制一份,然后在新线程里将这个拷贝对象以引用形式传给 process_data。所以你在 process_data 里修改的只是这个临时拷贝,主线程里的原始 parsed_data 自然不会有任何变化。
解决方法
有几种简洁的方式可以修复这个问题,这里给你列最常用的三种:
方案1:用 std::ref 传递原始引用
这是最直接的方式,通过 std::ref 包裹参数,明确告诉线程要传递原始变量的引用:
#include <thread> #include <functional> // 必须包含这个头文件才能使用std::ref void process_data(string& data); int main(){ string parsed_data = get_parsed_data(source_id); // 用std::ref包装,传递原始变量的引用 thread pre_process_thread(process_data, std::ref(parsed_data)); pre_process_thread.join(); populate_obj(parsed_data); return 0; }
这样 process_data 里的修改就会直接作用在主线程的 parsed_data 上了。
方案2:改用指针传递参数
如果你对引用包装不太习惯,也可以把函数参数改成指针,逻辑会更直观:
// 先修改process_data的参数类型为指针 void process_data(string* data); int main(){ string parsed_data = get_parsed_data(source_id); // 传递变量的地址 thread pre_process_thread(process_data, &parsed_data); pre_process_thread.join(); populate_obj(parsed_data); return 0; } // 对应的process_data实现也要调整 void process_data(string* data){ // 通过解引用修改原始变量 *data = "处理后的内容"; }
方案3:用Lambda表达式捕获引用
这种方式不需要修改 process_data 的参数类型,通过Lambda的引用捕获直接绑定原始变量:
int main(){ string parsed_data = get_parsed_data(source_id); thread pre_process_thread([&](){ // Lambda捕获parsed_data的引用,直接调用process_data process_data(parsed_data); }); pre_process_thread.join(); populate_obj(parsed_data); return 0; }
额外注意
你代码里主线程调用 join() 等待子线程完成的逻辑是安全的,能保证 parsed_data 在子线程运行期间始终有效,不会出现悬空引用的问题。如果用 std::ref 记得一定要包含 <functional> 头文件,否则会出现编译错误。
内容的提问来源于stack exchange,提问作者Bhupesh Pant
相关产品推荐
相关产品推荐

