线程函数中的通用引用
Universal references in a thread function
我一直在学习完美转发和在函数模板中使用&&(请参阅我之前的问题),并想知道我在下面的StartDetachedThread()
中使用Args&&
是否合理:
#include <thread>
class CObject {};
void MyThreadFunc(CObject&)
{
}
// ** Will not compile with this function declaration! **
void MyThreadFunc(CObject&&)
{
}
template<typename FunctionType, typename ...Args>
void StartDetachedThread(FunctionType func, Args&&... args)
{
thread([&]()
{
func(forward<Args>(args)...);
}).detach();
}
int main()
{
CObject object;
StartDetachedThread(MyThreadFunc, object);
CObject object2;
StartDetachedThread(MyThreadFunc, std::move(object2));
return 0;
}
此代码只是创建一个分离的线程,运行提供的函数,将提供的参数传递给它。
然而,VS 2017抱怨:
'StartDetachedThread': no matching overloaded function found
'void StartDetachedThread(FunctionType,Args &&...)': could not deduce template argument for 'FunctionType'
1)我知道传递给thread
构造函数的参数首先被复制,然后通过引用传递给新线程,那么当我传递右值引用时,我尝试调用MyThreadFunc(CObject&&)
永远不会起作用吗?
2)拥有StartDetachedThread(FunctionType&& func, Args&&... args)
有什么价值 - 或者&&
对FunctionType
来说是不必要的?
3)在启动这样的线程时,使用Args&&
有什么价值吗,或者我应该始终使用Args
?
你的代码中的问题与std::thread
无关,这是因为MyThreadFunc
在这种情况下是模棱两可的:
// Which MyThreadFunc should be used?
StartDetachedThread(MyThreadFunc, object);
关于您的问题:
1) 我知道传递给线程构造函数的参数首先被复制,然后通过引用传递给新线程,[...]
在您的示例中,唯一的副本是 lambda 的副本。此处不复制参数,如果您希望复制参数,则应使用如下内容:
std::thread(std::move(func), std::forward<Args>(args)...).detach();
。将参数转发到构造函数std::thread
。
这样更安全。— 想想如果函数StartDetachedThread
在线程仍在运行时结束会发生什么?
如果使用它,则需要显式告诉编译器要使用std::ref
调用object1
的参考版本:
CObject object;
StartDetachedThread<void (CObject&)>(MyThreadFunc, std::ref(object)); // std::ref
CObject object2;
StartDetachedThread<void (CObject&&)>(MyThreadFunc, std::move(object2));
2)拥有
StartDetachedThread(FunctionType&& func, Args&&... args)
有什么价值 - 或者&&
对FunctionType
来说是不必要的?3)在启动这样的线程时,使用
Args&&
有什么价值吗,或者我应该始终使用Args
?
使用转发引用可以调用StartDetachedThread
而无需移动所有内容。如果您使用上述方式构造std::thread
,那么无论如何都会为func
和args
制作副本。
问题是编译器无法推断所需的MyThreadFunc
重载。 至少有两种方法可以修复它:
-
重命名其中一个函数,以便更清楚地了解您想要哪个函数。
-
使用显式模板参数:
StartDetachedThread<void (CObject&)>(MyThreadFunc, object); StartDetachedThread<void (CObject&&)>(MyThreadFunc, std::move(object2));
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 无法将右值引用函数与 GCC 匹配
- C ++引用函数参数似乎包含原始对象的副本,而不是充当"real reference"
- 通过引用函数传递指针参数是什么意思?
- 常量引用函数参数的地址何时唯一?
- 我想了解为什么在这个例子中使用引用函数?或者引用在c++函数中的重要性
- C++ 通过引用函数传递数组,但内容保持不变
- 用数组或指针引用函数?
- 引用函数如何"int &foo();"工作?
- 常量引用函数参数:是否可以禁止临时对象?
- 计算在代码中引用函数的次数
- <initializer_list> 引用函数
- 字符串引用(函数)的差异
- 在类中引用函数时的"No Matching Function for Call"
- 无法通过引用函数"calcValues"中"firstNum"和"secondNum"变量来更改值
- 尝试引用已删除的函数(不引用函数)
- 引用函数指针
- 引用函数按值和自动返回
- 为什么我们可以取消引用函数指针
- 通过引用函数传递值的目的是什么