vs2019 cpp20 规范的线程头文件 <thread> 注释并探讨两个问题

本文主要是介绍vs2019 cpp20 规范的线程头文件 <thread> 注释并探讨两个问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

(1)学习线程,与学习其它容器一样,要多读 STL 库的源码。很多知识就显然而然的明白了。也不用死记硬背一些结论。上面上传了一份注释了一下的 源码。主要是补充泛型推导与函数调用链。基于注释后的源码探讨几个知识点。 STL 库的多线程,从语言上支持多线程编程,屏蔽了操作系统上的内核函数差异。
(2)结论一 : 能作为线程中的函数执行,该函数的形参应是值传递,或者是右值引用;不能是左值引用,否则编译不通过。举例如下图:

在这里插入图片描述

函数形参是左值引用则直接报错:

在这里插入图片描述

(3) 为什么会如此呢?这要从 STL 库的源码开始。虽然我理解的不深,欢迎一起探讨。首先看下 thread 类的数据结构:

在这里插入图片描述

接着要看看 thread 的构造函数:

在这里插入图片描述

接着进入 STL 中的源码:

在这里插入图片描述

接着看下在 thread 里是如何处理传递给待执行函数的实参的。从上图也可以看出,STL 用 tuple 元组来存储实参,但先用 decay_t 模板对实参的类型进行了处理。 decay 英文意思是衰减,消退,在代码里的含义,结合其定义,就是去除实参类型上的各种修饰符,只保留关于实参的最基本的类型(这就导致了实参向形参的值传递),decay_t 的定义如下(c++ 学习的难点就在于泛型推导,语法规则不多,但运用语法自洽的编写大型的具有功能的程序段,就难了):

在这里插入图片描述

decay 需要的其它模板定义:

在这里插入图片描述

以及:

在这里插入图片描述

所以可见,在 thread 中构建的 tuple 元组,将只包含最基本的不含引用 ,const ,volatile 等修饰符的类型。
接着在这一行代码里构建元组,并用实参对其初始化,并用独占智能指针指向这个新创建的 tuple 元组,其实这个元组就是将来线程执行时 的形参值,这些也作为函数中的局部变量的形参在内存中的位置。所以可以得出结论,线程中的函数,其形参是独一无二的,与 main 函数中创建线程时传递的实参没有任何关系。但 线程中待执行函数的形参,虽已生成数据,但这些形参无名,只有地址。其符合右值引用的定义与值传递的定义,但唯独不符合左值引用的定义。左值引用要求引用的值已经有名称,可是 tuple 中这些新生成的数据,留给将来待执行函数的形参使用,还不具有名字。用左值引用引用这些数据是非法的。这就要求待执行的函数形参应该如何写,应符合相关语法语义的格式。这符合我们以前学习的知识。

在这里插入图片描述

下面给出 _Get_invoke ,该函数很简单,就是给出线程中待执行函数的起始地址:

在这里插入图片描述

接着附上关于 全局 invoke 的源码与注释,很长,仅供参考。咱们还是要结合源代码,图片只是示意:

在这里插入图片描述

以及其它辅助理解的注释:

在这里插入图片描述

以及:

在这里插入图片描述

至此,咱们基本清楚了线程中待执行函数的启动流程,准备过程,以及函数形参是如何产生的。谢谢阅读。

(4)接着谈下第二个知识点:涉及线程中待执行函数的形参的生存周期。显然,函数形参的生存周期可能很长,是伴随线程存在,伴随其函数存在的。但这些形参数据是在 thread 这个类的构造函数执行时分配到内存的。显然独占指针 _Decay_copied 指向的存储形参数据的 tuple 元组,不应随着 _Decay_copied 这个智能指针的生存周期结束而到期。这是从以下代码发现出来的:

在这里插入图片描述

以下给出独占指针的相关成员函数的定义:

在这里插入图片描述

谢谢阅读。剩余的 join ,detach 结合源码就好理解了。很短的源代码。

这篇关于vs2019 cpp20 规范的线程头文件 <thread> 注释并探讨两个问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/984295

相关文章

mybatis和mybatis-plus设置值为null不起作用问题及解决

《mybatis和mybatis-plus设置值为null不起作用问题及解决》Mybatis-Plus的FieldStrategy主要用于控制新增、更新和查询时对空值的处理策略,通过配置不同的策略类型... 目录MyBATis-plusFieldStrategy作用FieldStrategy类型每种策略的作

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

Python Jupyter Notebook导包报错问题及解决

《PythonJupyterNotebook导包报错问题及解决》在conda环境中安装包后,JupyterNotebook导入时出现ImportError,可能是由于包版本不对应或版本太高,解决方... 目录问题解决方法重新安装Jupyter NoteBook 更改Kernel总结问题在conda上安装了

pip install jupyterlab失败的原因问题及探索

《pipinstalljupyterlab失败的原因问题及探索》在学习Yolo模型时,尝试安装JupyterLab但遇到错误,错误提示缺少Rust和Cargo编译环境,因为pywinpty包需要它... 目录背景问题解决方案总结背景最近在学习Yolo模型,然后其中要下载jupyter(有点LSVmu像一个

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

解决jupyterLab打开后出现Config option `template_path`not recognized by `ExporterCollapsibleHeadings`问题

《解决jupyterLab打开后出现Configoption`template_path`notrecognizedby`ExporterCollapsibleHeadings`问题》在Ju... 目录jupyterLab打开后出现“templandroidate_path”相关问题这是 tensorflo

如何解决Pycharm编辑内容时有光标的问题

《如何解决Pycharm编辑内容时有光标的问题》文章介绍了如何在PyCharm中配置VimEmulator插件,包括检查插件是否已安装、下载插件以及安装IdeaVim插件的步骤... 目录Pycharm编辑内容时有光标1.如果Vim Emulator前面有对勾2.www.chinasem.cn如果tools工

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明