C++面向对象(OOP)编程-线程返回值
函数可以有返回值,那么线程作为一个handler是如何返回值的呢?在C语言中线程可以直接返回值,然后通过thread.join(返回值)来获取,但是C++不支持这样做,C++中是怎么返回线程的返回值的呢?本文将会比较详细的介绍C语言线程的返回值,以及几种C++线程替代返回值的方法。
🎬个人简介:一个全栈工程师的升级之路!
📋个人专栏:C/C++精进之路
🎀CSDN主页?发狂的小花
🌄人生秘诀:学习的本质就是极致重复!
目录
1 C语言线程
1.1?pthread
????????在C语言中,可以使用POSIX线程库(pthread)来实现多线程编程。使用pthread库可以创建、同步和销毁线程。头文件是<pthread.h> 。
1.2 C语言线程
1.2.1 步骤
? ? ? ? (1)包含头文件?#include <pthread.h>
????????(2)申请线程对象,pthread_t thread1;
? ? ? ? (3)创建线程 pthread_create(&thread1,NULL,handler,&in);
1.2.2?pthread_create参数说明
? ? ? ? ? ? ? ? 参数说明:
? ? ? ? ? ? ? ? 第一个参数:thread1为线程对象地址
? ? ? ? ? ? ? ? 第二个参数:线程属性,pthread 线程属性包括:
? ? ? ? ? ? ? ? ? ? ? ? (1)调度策略,
? ? ? ? ? ? ? ? ? ? ? ? (2)调度的优先级,
? ? ? ? ? ? ? ? ? ? ? ? (3)线程的分离状态(分离线程:主动结束 和 可汇合线程:等待原有创建线程结束 ? ? ? ? ? ? ? ? ? ? ? ?才结束,即pthread_ioin()调用后,该子线程结束),
? ? ? ? ? ? ? ? ? ? ? ? (4)线程ID
? ? ? ? ? ? ? ? ? ? ? ? (5) 线程的继承性?
? ? ? ? ? ? ? ? 第三个参数:线程handler处理函数
? ? ? ? ? ? ? ? ? ? ? ? 一般定义为 void * handler(void *data){}; 如果需要返回值,可以申请堆空间返回
? ? ? ? ? ? ? ? ? ? ? ? pthread_join(thread_id,void * (ret)); void *ret是返回值的地址,可以用来得到返回
? ? ? ? ? ? ? ? ? ? ? ? 值的地址?
? ? ? ? ? ? ? ? 第四个参数: ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? 线程处理函数的输入参数,用来传参给处理函数 ?
1.2.3 pthread_join参数说明
? ? ? ? pthread_join(argv1,argv2);?
? ? ? ? ? ? ? ? 参数说明:
? ? ? ? ? ? ? ? ? ? ? ? argv1 为线程对象
? ? ? ? ? ? ? ? ? ? ? ? argv2 这里传入的二维指针,指的是存储返回值地址的指针的地址
????????
以下是一个简单的示例代码:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void *print_hello(void *arg) {
printf("Hello from thread %ld\n", (long)arg);
return NULL;
}
int main() {
pthread_t thread1, thread2;
int rc1, rc2;
long t1 = 1, t2 = 2;
/* Create independent threads each of which will execute function */
rc1 = pthread_create(&thread1, NULL, print_hello, (void *)t1);
if (rc1) {
fprintf(stderr, "Error: Unable to create thread %d", rc1);
exit(-1);
}
rc2 = pthread_create(&thread2, NULL, print_hello, (void *)t2);
if (rc2) {
fprintf(stderr, "Error: Unable to create thread %d", rc2);
exit(-1);
}
/* Wait till threads are complete before main continues. */
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
? ? ? ? 运行结果:
????????
1.3 C语言线程返回值
如下实现了线程返回值:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void * add1_handler(void *arg)
{
int *ret = (int*)malloc(sizeof(int));
*ret = *((int*)arg) + 1;
return ret;
}
int main() {
pthread_t thread1;
int in = 34;
int rc1 = 0;
/* Create independent threads each of which will execute function */
rc1 = pthread_create(&thread1, NULL, add1_handler, (void*)&in);
if (rc1) {
fprintf(stderr, "Error: Unable to create thread %d", rc1);
exit(-1);
}
/* Wait till threads are complete before main continues. */
int *ret_value = NULL;
pthread_join(thread1, (void**)(&ret_value));
printf("最终的结果: %d \n",*ret_value);
free(ret_value);
return 0;
}
? ? ? ? 运行结果:
最终的结果: 35
2 C++线程
2.1 thread
C++线程是一种轻量级的执行单元,可以在单个程序中并发执行多个任务。C++标准库提供了对线程的支持,包括创建、同步和销毁线程等功能。
在C++中,可以使用<thread>
头文件中的函数来创建和管理线程。以下是一个简单的示例代码:
#include <iostream>
#include <thread>
void print_hello() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
// 创建一个新线程并执行print_hello函数
std::thread t(print_hello);
// 等待线程执行完成
t.join();
return 0;
}
? ? ? ? 运行结果:
2.2 C++线程调用参数种类
2.2.1 函数指针
可以将函数指针作为参数传递给std::thread
类来定义线程。
#include <iostream>
#include <thread>
void print_hello() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
std::thread t(&print_hello); // 使用函数指针定义线程
t.join();
return 0;
}
? ? ? ? 运行结果:
2.2.2?Lambda表达式
可以使用Lambda表达式来定义线程。
#include <iostream>
#include <thread>
int main() {
std::thread t([]{
std::cout << "Hello from thread!" << std::endl;
}); // 使用Lambda表达式定义线程
t.join();
return 0;
}
? ? ? ? 运行结果:
2.2.3?成员函数
可以将成员函数作为参数传递给std::thread
类来定义线程。
#include <iostream>
#include <thread>
class MyClass {
public:
void print_hello() {
std::cout << "Hello from thread!" << std::endl;
}
};
int main() {
MyClass obj;
std::thread t(&MyClass::print_hello, &obj); // 使用成员函数定义线程
t.join();
return 0;
}
? ? ? ? 运行结果:
? ? ? ? 上述代码使用成员函数作为线程的handler,并把实例传入,以达到调用某一对象的成员函数。
2.2.4 函数对象
可以将函数对象作为参数传递给std::thread
类来定义线程。函数对象需要重载operator()
运算符。
#include <iostream>
#include <thread>
class MyFunctor {
public:
void operator()() {
std::cout << "Hello from thread!" << std::endl;
}
};
int main() {
MyFunctor functor;
std::thread t(functor); // 使用函数对象定义线程
t.join();
return 0;
}
? ? ? ? 运行结果:
? ? ? ?
? ? ? ? 上述代码通过运算符()重载实现用函数对象完成线程的参数。
2.3?C++线程返回值
????????由于C++线程的join不支持接收参数,因此不可以通过这种方式返回值,只能通过传入共享指针或者对象,以及使用future和promise来实现线程返回值。
2.3.1 共享指针
? ? ? ? 本质上传递变量、对象等都是共享指针。
#include <iostream>
#include <thread>
using namespace std;
void * add1_handler(void *arg)
{
*(int*)arg = 56;
}
int main() {
int value = 11;
std::cout << "执行前value: " << value << std::endl;
std::thread t(&add1_handler,&value);
// 等待线程执行完成
t.join();
std::cout << "执行后value: " << value << std::endl;
return 0;
}
? ? ? ? 运行结果:
执行前value: 11
执行后value: 56
2.3.2 future和promise配合实现
????????std::future和std::promise是封装好的两个类模板,这两个类需要配合使用,他们的头文件是#include <future>
????????std::future,它表示存储着一个未来会被初始化的变量。这个变量可以通过std::future提供的成员函数std::future::get()来得到。如果在这个变量被赋值之前就有别的线程试图通过std::future::get()获取这个变量,那么这个线程将会被阻塞到这个变量可以获取为止。
????????std::promise同样也是一个类模板,这个对象承诺在未来一定会初始化一个变量(这个变量也就是std::future中的变量)。
????????每一个std::promise对象都有一个与之关联的std::future对象。当std::promise设置值的时候,这个值就会赋给std::future中的对象了。
#include <iostream>
#include <future>
#include <thread>
void func2(int x, int y,std::promise<int> &promiseObj) {
promiseObj.set_value(x+y);
}
int main()
{
//计算(a+b)/(x+y)
//用三个线程,一个线程计算a+b,另一个线程计算x+y
int a, b, x, y;
a = 10, b = 8, x = 2, y = 4;
int sum1, sum2;
//声明一个类
std::promise<int> promiseObj;
//将future和promise关联
std::future<int> futureObj = promiseObj.get_future();
//模板传参的时候使用ref,否则传参失败
std::thread t1(func2, a, b, ref(promiseObj));
t1.join();
//获取值
sum1 = futureObj.get();
std::cout << "sum1=" << sum1 << std::endl;
//不能直接复用上面的future和promise
std::promise<int> promiseObj2;
std::future<int> futureObj2 = promiseObj2.get_future();
std::thread t2(func2, x, y, ref(promiseObj2));
t2.join();
sum2 = futureObj2.get();
std::cout << "sum2=" << sum2 << std::endl;
std::cout << "sum1/sum2=" << sum1 / sum2 << std::endl;
return 0;
}
? ? ? ?运行结果:
sum1=18
sum2=6
sum1/sum2=3
? ? ? ? 分析结果可知,上述代码实现了线程返回值,通过将一个promise对象绑定到一个future上,通过传入promise对象作为线程的返回值,最终由future获取promise的值,本质上也是一种共享指针的方式。
🌈我的分享也就到此结束啦🌈
如果我的分享也能对你有帮助,那就太好了!
若有不足,还请大家多多指正,我们一起学习交流!
📢未来的富豪们:点赞👍→收藏?→关注🔍
感谢大家的观看和支持!最后,?祝愿大家每天有钱赚!!!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!