线程传参,是否有副本。以及C2672“std::invoke”错误
线程传参,值传递和单独的&传递,线程都会保留一份副本,不会对函数外的值造成影响。外边的值释放了,也不影响线程函数里的值。有种普通函数值传递的感觉,里外互不相干。
指针传递,& + std::ref 组合,才是传真身,不会有副本。等效普通函数的指针传递和引用传递了。此时需要注意生命周期内的内存值的改变和释放,否则可能异常。
指针传递:
void threadFunction(int* ptr) { // 在线程中修改ptr指向的值 } int main() { int x = 0; std::thread t(threadFunction, &x); t.join(); return 0; }
& + std::ref 组合
void threadFunction(int& ref) { // 在线程中修改ref的值 } int main() { int x = 0; std::thread t(threadFunction, std::ref(x)); // 使用std::ref确保以引用方式传递 t.join(); return 0; }
当把std::ref去掉后,会报C2672“std::invoke”错误。这是编译器的善意提醒,认为你想传真身,但是传的不对,可以加上std::ref,或者函参用const修饰。
本质原因多线程传参报错 :错误 C2672 “std::invoke”: 未找到匹配的重载函数_error c2672: “invoke”: 未找到匹配的重载函数-CSDN博客
但是编译器也不足够强大,传结构体时,就不会报这个错误
struct MyStruct { int a = 0; }; void threadFunction(MyStruct& ref) { // 在线程中修改ref的值 ref.a = 20; } int main() { MyStruct ms; std::thread t(threadFunction, ms); //不会报错,传的是副本 t.join(); return 0; }
【单独的&传递】
函参推荐写法:
简单类型 变量名。对于简单类型,如int等,用值传递安全,不要用引用。
const 类 &类对象。对于类、struct等用引用。这样编译器不会报错,而且虽然不是传真身,但是减少了一次拷贝构造。
thread的机制是先把传的类对象构造出来,即临时对象(第一次构造,注意不是拷贝构造),对临时对象进行拷贝(第二次构造,拷贝构造),再传到函参,值传递方式会再次拷贝构造(第三次构造,拷贝构造)。
void MyThread1(int nVal) {} void MyThread2(const Test &t) {}
参考
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?