多线程带回返回值操作

张开发
2026/4/30 9:39:32 15 分钟阅读

分享文章

多线程带回返回值操作
1、在C中call指的是直接的函数调用通过()运算符直接调用函数invoke是更广义的调用机制指通过各种方式执行可调用对象强调调用机制本身call是invoke的一种形式。2、左值引用指的是传统的C引用绑定到左值有名字、有地址的对象的意思右值引用是C11引入的绑定到右值临时对象、将亡值、即将销毁的对象用于实现移动语义和完美转发。3、std::ref()是C标准库中的一个重要工具函数用于生成一个引用包装器将引用转换为可复制对象。为什么要使用std::ref(),在C中引用本身不可复制、不可重新绑定但有些场合比如函数对象、模板、多线程需要传递可复制的对象这时候用std::ref()就可以生成一个引用包装器将引用转换为可复制对象。4、std::ref()返回一个std::reference_wrapperT对象然后调用其get()函数可以获得对原始对象的引用。auto ref_warpper std::ref(value);ref_warpper.get() 1;就可以将原对象修改。5、std::ref()非常重要在如下3种情况下经常使用1在lambda中修改外部变量#include algorithm #include vector void example2() { std::vectorint nums {1, 2, 3, 4, 5}; int sum 0; // 使用 std::ref 传递可修改的引用 std::for_each(nums.begin(), nums.end(), [sum](int n) { sum n; }); // 或者使用 std::ref sum 0; auto sum_ref std::ref(sum); std::for_each(nums.begin(), nums.end(), [sum_ref](int n) mutable { sum_ref.get() n; }); std::cout Sum: sum std::endl; // 15 }2在std::bind中传递引用参数#include functional void modify(int x, int value) { x value; } void example3() { int value 10; // 使用 std::ref 传递引用 auto func std::bind(modify, std::ref(value), 20); func(); std::cout Value after bind: value std::endl; // 20 }3在std::thread中传递引用#include thread void increment(int counter) { for (int i 0; i 1000; i) { counter; } } void example4() { int counter 0; std::thread t1(increment, std::ref(counter)); std::thread t2(increment, std::ref(counter)); t1.join(); t2.join(); std::cout Counter: counter std::endl; // 2000 }6、值语义是指对象在传递和赋值时默认进行值的复制产生一个独立的副本。这是C的核心特性之一与引用语义相对在类中表示为有拷贝构造和拷贝赋值不可复制对象私有拷贝构造和拷贝赋值拷贝构造和拷贝赋值 delete但不影响移动构造和移动赋值比如说智能指针。std::thread的参数按值存储的确保线程的生命周期独立避免悬空引用std::thread的构造函数参数是万能引用但是内部存储时按值存储。templatetypename Function,typename... Argsthread(Function f,Args... args);这里是万能引用参数可以是左值也可以是右值{std::tuplestd::decay_tF,std::decay_tArgs... state(std::forwardFf,std::forwardArgs(args)...)//这里会拷贝/移动}关键std::decay_tArgs会移除引用和移除cv限定符数组转指针函数转函数指针7、引用是不可复制对象使用type_traits对可复制性进行检查std::cout int is copyable: std::is_copy_constructible_vint std::endl; //true,整数是可复制对象。8、多线程中只有全局区和静态区的数据是每个线程共享的如果在栈区需要使用子线程把值返回来需要在参数中传递引用包装器因为线程是不可复制对象因此不能直接传递引用需要传递引用包装器(一定要注意栈区的对象生命周期)。#include thread void threadFunc(int a) { a 10; } void startThread() { int a 0; std::thread thread01(threadFunc, std::ref(a)); thread01.join(); }//函数结束时a被销毁但是thread01还在运行访问a会导致未定义行为。因此必须加thread01.join(); int main() { startThread(); return 0; }1通过引用包装器做参数带回线程返回值。void func(int x,int y,int result)//这里的result引用作为返回值 { result x y; } int main() { int result 0; int a 1; int b 2; //std::thread thread01(func,a,b,result);//错误 std::thread thread01(func,a,b,std::ref(result));//正确 }2函数对象做线程函数示例修改的是拷贝的f的result而不是线程外面的f的result因此不能带回返回值或者不能修改f的成员。struct MyFunc { int operator()(int x,int y) { result x y; } int result 0; }; int main() { int a 1; int b 2; MyFunc myFunc; std::thread thread02(myFunc,a,b); std::cout f.result std::endl; }3将类对象的this指针或对象地址作为第一个参数调用类的成员函数。#include iostream class MyClass { public: int sum(int x,int y) { result x y; } private: int result; }; int main() { int a 1; int b 2; MyClass myClass; std::thread thread01(MyClass::sum,myClass,a,b); std::cout myClass.result std::endl; }(4)使用lambda按引用捕获。int main() { int a 1; int b 2; int sum 0; std::thread thread01([sum](int x,int y){sum a b;},a,b) std::cout sum std:: endl; return 0; }#include thread #include iostream void myFunc(double param1, double param2, double result) { result param1 param2; } struct MyFunctor { void operator()(double param1, double param2) { result param1 param2; } double result 0; }; class MyClass { public: void sum(double param1, double param2) { result param1 param2; } double result 0; }; int main() { double a 1.1; double b 2.2; double result1 0; //std::thread thread1(myFunc, a, b, result1); std::thread thread1(myFunc,a,b,std::ref(result1)); MyFunctor f; std::thread thread2(f, a, b); MyClass obj; std::thread thread3(MyClass::sum, obj, a, b); double result2; std::thread thread4([result2](double param1, double param2) { result2 param1 param2; }, a, b); thread1.join(); thread2.join(); thread3.join(); thread4.join(); std::cout Result from thread1: result1 std::endl; std::cout Result from thread2: f.result std::endl; std::cout Result from thread3: obj.result std::endl; std::cout Result from thread4: result2 std::endl; }

更多文章