(1)传递临时对象作为线程参数

(2)传递类对象智能指针作为线程参数

(3)用成员函数指针做线程函数

在实际工作中我们要创建的线程可能不止一个,比如说我们要创建10个,编号从0到9,这10个线程会根据自己的编号确定自己要干的事情,这个线程如何知道自己的编号呢,这个就需要我们给线程传递参数(比如我们传递0123456789这10个数,那么线程就通过接收的这个参数就知道自己的编号了。)。

void myprint(const int &i,char *pmybuf)
{cout<<i<<endl;cout<<pmybuf<<endl;}
int main()
{//传递临时函数作为线程参数int mvar=1;int &mvary=&mvar;char mybuf[]=“this is a test”;//定义一个字符数组
//thread创建一个mytobj的对象
thread mytobj(myprint,mvar,mybuf);//第一个参数传递的是线程函数名,第二个开始传递参数(该参数是线程函数的第一个参数)第三个创建这个对象构造函数的第三个参数就是线程函数myprint这个函数的第二个参数。(所以第一个参数就是线程函数,后边第二、三个参数是这个线程函数的所有参数)mytobj.join();//等待子线程执行完毕cout<<"I Love China"<<endl;return 0;}

运行结果:

传进去的参数分别是1和this is a test!

上述要注意的问题1是:

假如我上边没有使用join,使用的是detach(),主线程和子线程分别执行自己的。那么有可能主线程先执行完了(主线程执行完了也无所谓,子线程在后台继续执行。)

上述我们看到了,子线程使用的参数是一个引用,mvar的一个引用,如果主线程先退出,那么mvar可能被系统回收了,那我们在子线程中用这个i的话会出问题吗?(打印地址查看后经实验虽然是安全的,但是不建议。)

三个的地址不一样说明一个问题,我们在myprint里边虽然使用的是引用,但是我们在创建thread对象Mytobj的时候,里边的mvar并不是真的用mvar的引用来绑这个mvar的,实际这里边他肯定是做了个复制,也就是说他是把mvar的值复制给了i,所以这个i不是一个真引用(因为i的地址跟mvar的地址不一样,作为引用来讲应该是一样的但实际是不一样的,所以说thread这个内部肯定做了一个复制,他把实际做的这个东西i不是一个引用(i并不是mvar的引用,实际是值传递,虽然myprint里边是引用但是实际是值传递,因为i跟其他的地址不一样),是一个值。所以说这里使用detach的话,虽然主线程可能先执行完,但是在子线程中因为i不是一个真引用,是一个复制的值,所以我们在子线程中用i应该是安全的(因为子线程中你用的并不是mvar值,是自己复制出来的一个值,所以是安全的),但是也不建议这么写)。

再看子线程中的第二个参数是否安全:

说明pmybuf指向的是mybuf的地址,那如果用detach运行的话,当主线程main函数先运行完了,内存就被系统回收了,那你在子线程中再使用这个指针就不安全了。如果要用detach参数创建线程的话,不推荐用引用,不推荐用指针(指针在detach子线程时绝对有问题的)。

怎么样将这个字符串mybuf传递到线程中来呢?

//将上边myprint函数做修改
void myprint(const int i,const string &pmybuf)
{cout<<i<<endl;cout<<pmybuf.c_str()<<endl;}
int main()
{//传递临时函数作为线程参数int mvar=1;int &mvary=&mvar;char mybuf[]=“this is a test”;//定义一个字符数组thread mytobj(myprint,mvar,mybuf);mytobj.join();//等待子线程执行完毕cout<<"I Love China"<<endl;return 0;}

地址查看:

上述要注意的问题2是:

thread mytobj(myprint,mvar,mybuf);//启动这个线程的话,我们希望是将mybuf字符数组转化成隐式字符串,然后我们在string中就可以使用string这个对象,这样的话线程就不会引用主线程也就是main函数中mypuf这段内存,那你mybuf这段内存,如果你主线程运行完了,销毁了这段内存,也不会影响我pmybuf内存的引用。但现在的问题是mypuf在什么时候转化为string?比如我这个mian函数都执行完了你才把mypuf往string转,那就太尴尬了,此时mupuf已经被系统回收了(因为mybuf是一个局部变量,属于主线程中的变量),回收了就没有办法转了。

需要将主函数中代码修改为:

thread mytobj(myprint,mvar,string(mybuf));//这里直接将mypuf转化成string对象,这是一个可以保证在线程中肯定有效的对象

使用mybuf临时构造了一个string对象,然后这个string对应myprint中的第二个参数string。为什么转化成临时的string对象就没有问题了呢?

class A
{
public:int m_i;A(int a):m_i(a){cout<<"A::A(int a)构造函数执行<<endl;"}//带一个参数的构造函数A(const A &a):m_i(a.m_i){cout<<"A::A(const A &a)构造函数执行<<endl;"}//拷贝构造函数}
void myprint(const int i,const A &pmybuf)
{cout<<&pmybuf<<endl;//这里打印的是pmybuf的地址return;
}
int main()
{int mvar=1;int mysecondpar=12;thread mytobj(myprint,mvar,mysecondpar);//我们希望mysecondpar转化成A类型对象传递给myprint的第二个人参数
//改造一下thread mytobj(myprint,mvar,A(mysecondpar));
}

上述在主线程结束之前,pmybuf一定是已经构造出来了,在这个值还是有效的时候我就已经构造出来了a对象传递到线程中去了,现在A对象就被保存到了pmubuf

C++:多线程中的小白(3)线程传参详解相关推荐

  1. C++11多线程第三篇:线程传参详解,detach()大坑,成员函数做线程参数

    文章目录 3.1 传递临时对象作为线程参数 3.1.1 要避免的陷阱(解释1) 3.1.2 要避免的陷阱(解释2) 3.1.3 总结 3.2 临时对象作为线程参数进一步详解 3.2.1 线程id概念 ...

  2. 第三节 线程传参详解、detach()大坑、成员函数做线程函数

    1.传递临时对象作为线程参数 原始的输入程序如下: #include <iostream> #include <thread>using namespace std;void ...

  3. Springboot传参详解

    作者简介 作者名:编程界明世隐 简介:CSDN博客专家,从事软件开发多年,精通Java.JavaScript,博主也是从零开始一步步把学习成长.深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢 ...

  4. C#进阶系列——WebApi 接口参数不再困惑:传参详解

    看这边文章时的疑惑是:WebApi中的参数加了[FromBody],不知所以然,就百度了下,看到了以下文章,和大家分享下: 原文链接:http://www.cnblogs.com/landeanfen ...

  5. python可变参数_Python 的四种共享传参详解

    点击上方"Python数据之道",选择"星标公众号" 精品文章,第一时间送达 作者 | 杨仁聪 编辑 | Lemon 出品 | Python数据之道 本文来自公 ...

  6. WebApi 接口参数不再困惑:传参详解

    阅读目录 一.get请求 1.基础类型参数 2.实体作为参数 3.数组作为参数 4."怪异"的get请求 二.post请求 1.基础类型参数 2.实体作为参数 3.数组作为参数 4 ...

  7. 【转】C#进阶系列——WebApi 接口参数不再困惑:传参详解

    阅读目录 一.get请求 1.基础类型参数 2.实体作为参数 3.数组作为参数 4."怪异"的get请求 二.post请求 1.基础类型参数 2.实体作为参数 3.数组作为参数 4 ...

  8. Spring/Boot/Cloud系列知识:SpringMVC 传参详解(下)

    (接上文<Spring/Boot/Cloud系列知识:SpringMVC 传参详解(上)>) 2.3.通过@PathVariable注解基于URL匹配符接收请求传参 为了便于开发人员实现更 ...

  9. Vue路由传参详解(params 与 query)

    Vue路由传参详解(params 与 query) 前言: 路由传参分为 params 传参与 query 传参 params 传参类似于网络请求中的 post 请求,params 传过去的参数不会显 ...

最新文章

  1. SSIS中的记录集目标
  2. [转] 微软轻量级 Web 开发平台 WebMatrix 发布
  3. 天梯 L2 这是二叉搜索树吗?
  4. ext store 数据修改_Vue 组件数据通信方案总结
  5. Flutter学习笔记02:初探Flutter项目
  6. 整数快速幂(原理+模板)
  7. System.Security.Cryptography.RSA.FromXmlString 系统找不到指定的文件和X509读取证书文件系统找不到指定的文件异常
  8. 【JSOI2014】【BZOJ5039】序列维护(线段树模板)
  9. spss显示客户端与服务器,spss客户端服务器结构
  10. L1-087 机工士姆斯塔迪奥
  11. 【国内chatgpt使用方法合集】(5月22日已更新)
  12. 一个文件权限问题 error writing to file C:/xxxxx.xx verify that you have acces to that directory
  13. 安装quagga(虚拟路由器)
  14. 多维泰勒网matlab,非线性系统多维泰勒网控制的稳定性分析及性能优化
  15. MFC界面开发工具BCG v31.1 - 控件功能增强
  16. 【极简版GH60】【GH60剖析】【五】壳和键帽的装配
  17. 操作系统——生产者消费者模型以及信号量
  18. 富士施乐再推“中国定制”新品 引领中小企业智能化移动办公潮流
  19. 达人评测i5 1340p和i7 1360p选哪个 i51340p和i71360p区别
  20. Ktx:简化Android开发的Kotlin库

热门文章

  1. 【CV】Numpy|Python中矩阵和数组乘法及向量相关问题
  2. 谷歌不更新android studio,彻底迈向64位:谷歌宣布 Android Studio 将停止 32 位版本更新...
  3. Only the original thread that created a view hierarchy can touch its views
  4. Java 构造方法与成员方法的区别
  5. JAVA用递归方法判断某个字串是否是回文
  6. JDBC学习DayTwo
  7. tomcat的webapps下没有出现配置过的文件夹
  8. pg_basebackup 配置 stream replication 异步/同步
  9. python之接口开发
  10. Oracle 表分区删除操作