国外做的比较好看的网站,苏州百度运营公司排名,WordPress二次元免费模板,搜索引擎查重正文
传参中的陷阱
1. 向std::thread 构造函数传参#xff1a;所有参数#xff08;含第1个参数可调用对象#xff09;均按值并以副本的形式保存在 std::thread 对象中的tuple里。这一点的实现类似于std::bind。如果要达到按引用传参的效果#xff0c;可使用std::ref来传递…正文
传参中的陷阱
1. 向std::thread 构造函数传参所有参数含第1个参数可调用对象均按值并以副本的形式保存在 std::thread 对象中的tuple里。这一点的实现类似于std::bind。如果要达到按引用传参的效果可使用std::ref来传递。
2. 向线程函数的传参由于std::thread 对象里保存的是参数的副本为了效率同时兼顾一些只移动类型的对象所有的副本均被std::move到线程函数即以右值的形式传入。
注意事项
1. 一个实参从主线程传递到子线程的线程函数中需要经过两次传递。第1次发生在 std::thread 构造时此次参数按值并以副本形式被保存。第2次发生在向线程函数传递时此次传递是由子线程发起并将之前std::thread内部保存的副本以右值的形式(std::move())传入线程函数中的。
2. 如果线程函数的形参为T、const T或T类型时std::thread的构造函数可以接受左值或右值实参。因为不管是左值还是右值在std::thread中均是以副本形式被保存并在第2次向线程函数传参时以右值方式传入而以上三种形参均可接受右值。
3. 而如果线程函数的形参为T时不管是左值还是右值的T类型实参都是无法直接经std::thread传递给形参为T的线程函数因为该实参数的副本会被std::move成右值并传递线程函数但T无法接受右值类型。因此需要以std::ref形式传入
4. 当向线程函数传参时可能发生隐式类型转换这种转换是在子线程中进行的。需要注意由于隐式转换会构造临时对象并将该对象是个右值传入线程函数因此线程函数的形参应该是可接受右值类型的T、const T或T类型但不能是T类型。此外如果源类型是指针或引用类型时还要防止可能发生悬空指针和悬空引用的现象。 上面需要注意的第4 点中谈到这种隐式转换可能会产生临时对象。在之前的描述中关于 std::reference_wrapper 的隐式类型转换并不涉及临时对象的构造。这里的隐式转换不创建新的对象而是提供对已存在对象的引用。
我将进一步解释这一点
std::reference_wrapper 和隐式类型转换
当 std::reference_wrapperT 实现隐式类型转换操作符operator T() const它并不创建新的 T 类型的对象。相反它返回它所包装的现有对象的引用。这是一个重要的区别因为返回引用意味着没有新对象的构造只是提供对原始对象的直接访问。
何时会发生临时对象的构造
临时对象的构造通常发生在如下情况
当函数返回一个非引用类型的值时。当创建一个新对象并使用另一个对象来初始化它时如复制或移动构造函数调用。当类型转换需要创建一个新的类型实例时如从一种复杂类型到另一种类型的转换如果没有直接的引用传递路径。
在 std::reference_wrapper 使用的上下文中
不会 创建新的 T 类型的对象因为类型转换操作符返回的是一个已经存在的对象的引用。
结论
因此在使用 std::reference_wrapper 时与其隐式转换相关的操作只是提供一个现有对象的引用而不是创建一个新的对象。这保证了效率和引用的正确传递是在多线程编程中安全使用对象引用的有效方式。