构造std::thread对象过程中的详细信息
Details in the process of constructing a std::thread object
我对构造std::thread
对象的细节很感兴趣(也很困惑)。根据cppreference,线程函数和所有参数都被值复制到某个线程可访问的存储中,然后调用。
1)这个线程可访问的存储究竟是什么它在语义上是否等同于某种线程本地存储,并且在线程函数返回后对变量进行销毁?
2)传递给线程函数时,参数的值类别是什么cppreference上的描述表明它们是作为l-value传递的(不管怎样,它们都是给定的名称)。我对GCC和clang的测试似乎表明了相反的情况,即r值。具体来说,以下代码不编译:
void f(int& a) {
std::cout << ++a << 'n';
}
int main() {
std::thread t(&f, 1);
t.join();
return 0;
}
如果我们将f
更改为,它会编译
void f(int&& a) {
std::cout << ++a << 'n';
}
int main() {
std::thread t(&f, 1);
t.join();
return 0;
}
那么,标准对此有何规定?
1)这个"线程可访问存储"的文本位在标准中没有直接表示。标准只是简单地说,函数是用decay_copy
获得的参数调用的。
2) 如果你仔细研究decay_copy
,你会发现它通过值返回(因为它的返回类型是某种东西的std::decay
)。因此,函数f
是用rvalue参数(实际上是prvalue参数)调用的。
如果要传递lvalues(references),可以使用std::ref
和std::cref
来包装它们。
确切的报价,C++11 30.3.1.2/4:
效果:构造类型为
thread
的对象。执行的新线程执行INVOKE(DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)
,并调用DECAY_COPY
正在构造线程中进行评估。此调用的任何返回值都是已忽略。[注意:这意味着调用f
副本时未抛出的任何异常将在构造线程中抛出,而不是在新线程中抛出-结束注释]如果INVOKE(DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)
终止如果出现未捕获的异常,则应调用std::terminate
。
DECAY_COPY
在30.2.6/1:中定义
在本条款的几个地方,使用了操作
DECAY_COPY(x)
。所有这些用法都意味着调用函数decay_copy(x)
并使用结果,其中decay_copy
定义如下:template <class T> typename decay<T>::type decay_copy(T&& v) { return std::forward<T>(v); }
INVOKE
在20.8.2中定义的方式与cppreference描述您提供的链接中的调用的方式大致相同。
- 如何使用软化工具包从 OPC UA 服务器异步读取操作回调中的数据值响应中获取 NodeId 详细信息
- protobuf,如何在protobuf消息中遍历所有集合字段,我不知道详细信息?(C++)
- 如何在编译过程中输出C 类型信息
- 如何在文本文件中搜索员工记录(按名称)并仅显示其详细信息?
- 主 - Embarcadero C++生成器 10.2 中的详细信息数据集
- 如何获取有关protobuf解析过程中生成的错误的更多详细信息?(C++)
- 如何使用在窗口中使用C++从CreateToolhelp32Snapshot获取64/32位进程详细信息和进程信息
- 如何在C++中以编程方式检索 64 位进程的详细信息
- 我们可以从设备句柄中获取设备对象详细信息 /名称吗?
- 在C++中获取 Linux 内核模块的详细信息
- 构造std::thread对象过程中的详细信息
- 在比较过程中返回节点信息
- 模板或函数参数作为 doxygen 中的实现详细信息
- 为什么 Boost 和其他库的某些部分(如 Folly)在详细信息子文件夹中
- 在类定义中使用结构的详细信息和优点
- 在 C++ 中设置内置 exe 的 Windows 文件详细信息
- 方法在C++中存储一些数字(有关详细信息,请参阅内部)
- 当全局函数需要指向 impl 的指针时,如何防止 impl 详细信息出现在头文件中
- 如何在二进制文件(.net或非托管文件)中注入/更新Version和其他详细信息
- 我在 c++ 中的赋值重载运算符有什么问题?(包括详细信息)