线程初始函数的定义及C++20相关标准疑问
关于C++标准中“线程初始函数”的定义疑问与解答
引用的C++20标准条款
C++20草案的[except.handle]/12条款指出:线程存储期对象的析构函数或命名空间作用域线程存储期对象的构造函数抛出的异常,无法被线程初始函数的函数try块捕获;[except.terminate]/1.10条款提到,当线程初始函数因异常退出时会终止异常处理。
核心疑问
- 什么是“线程初始函数”?它是
main函数吗?是[thread.thread.constr]/6中规定的std::invoke实现?还是其他内容? - 曾有答复称“线程初始函数是线程运行的第一个函数,且该函数始终是
std::invoke的实现”,此说法是否正确?若不正确,标准语境中“线程初始函数”的准确定义是什么?
标准语境下的定义与解答
主线程的初始函数是
main函数
程序启动时创建的主线程,其初始函数就是标准规定的main函数——主线程从main开始执行,这是明确的。std::thread创建的子线程的初始函数
对于通过std::thread构造的子线程,其初始函数并非你直接传入的可调用对象,也不是std::invoke本身:
根据[thread.thread.constr]/6的规定,std::thread会将用户传入的可调用对象和参数包装,然后通过std::invoke执行,但线程实际开始运行的顶层入口函数才是标准语境中的“线程初始函数”——这个顶层函数负责线程初始化(比如处理线程存储期对象的构造前置逻辑)、调用std::invoke执行用户逻辑,以及线程退出时的清理工作。对之前答复的验证
- 前半句“线程初始函数是线程运行的第一个函数”是正确的;
- 后半句“始终是
std::invoke的实现”不准确:std::invoke是用来执行用户提供的可调用对象的工具,线程初始函数是包含std::invoke调用的顶层入口,二者不是同一概念。
- 结合条款语境补充
[except.handle]/12提到的异常无法被捕获,原因是命名空间作用域的线程存储期对象构造发生在线程初始函数执行之前,线程存储期对象的析构发生在线程初始函数退出之后,自然不在其函数try块的处理范围内;而[except.terminate]/1.10的逻辑是:如果线程初始函数(顶层入口)因未被捕获的异常退出,会直接触发std::terminate终止程序。
内容的提问来源于stack exchange,提问作者Sally Ibram
相关产品推荐
相关产品推荐

