上一篇文章中讲了thread的四种构造函数,接下来给大家讲一讲thread的参数传递。
1.初始化构造函数
利用初始化构造函数创建对象,第一个位置必须要传入一个可调用对象。c++ 中的可调用对象大概有这么几种:普通函数 ,类成员函数,类静态函数,仿函数,函数指针,lambda表达式,std::function。不了解可调用对象的可以戳这里,我写的另一篇关于可调用对象的文章。
(1)普通函数
用普通函数来初始化thread对象很简单,只需要把函数名传进去即可,函数中的参数按照顺序传入:
#include
#include
void fun(int a,int b)
{
printf("%d\n",a+b);
}
int main()
{
int a =1;
int b =2;
std::thread t(fun,a,b);
t.join();
}
输出结果为 : 3
(2)类成员函数
类成员函数是有真正地址的,利用 &类名::函数名 可以拿到成员函数的地址。注意,最好先创建一个了类对象,不建议用临时对象。第二位参数传入该对象。
#include
#include
class A
{
public:
void fun(int a,int b)
{
printf("%d\n",a+b);
}
};
int main()
{
int a =1;
int b =2;
A c;
std::thread t(&A::fun,c,a,b);
t.join();
}
输出结果为 : 3
(3)类静态成员函数
类静态成员函数不需要指定类对象。
#include
#include
class A
{
public:
static void fun(int a,int b)
{
printf("%d\n",a+b);
}
};
int main()
{
int a =1;
int b =2;
std::thread t(&A::fun,a,b);
t.join();
}
输出结果为: 3
(4) 仿函数(即用类对象创建线程)
仿函数是使用类来模拟函数调用行为,我们只要重载一个类的operator()方法,即可像调用一个函数一样调用类。这种方式用得比较少。
#include
#include
class A
{
public:
void operator()(int a,int b)//实现了对()的重载
{
printf("%d\n",a+b);
}
};
int main()
{
int a =1;
int b =2;
A c;
std::thread t(c,a,b);
t.join();
}
输出结果为 : 3
我们只需要在类的内部对() 进行重载,然后就可以将该类的对象作为可调用对象初始化thread。
(5)函数指针
没啥说的,函数指针的使用,和回调函数用法差不多。
#include
#include
void fun(int a, int b)
{
printf("%d\n", a + b);
}
int main()
{
int a = 1;
int b = 2;
void (*p)(int, int) = fun;
std::thread t(p, a, b);
t.join();
}
输出结果为 : 3
(6)lambda表达式
将匿名函数作为可调用对象创建thread。
#include
#include
int main()
{
int a = 1;
int b = 2;
auto c = [](int a, int b) {printf("%d\n", a + b); };
std::thread t(c, a, b);
t.join();
}
输出结果为 : 3
(7) std::function
std::function 可以用来描述C++中的可调用实体,它可以兼容所有可调用对象,自然也可以通过它来初始化thread对象。
#include
#include
#include
std::function<void(int, int)> Function;
//普通函数
void fun(int a,int b)
{
printf("普通函数:%d\n", a + b);
}
void fun2(int a, int b)
{
printf("函数指针:%d\n", a + b);
}
class A
{
public:
//类成员函数
void fun1(int a, int b)
{
printf("类成员函数:%d\n", a + b);
}
//静态成员函数
static void fun2(int a, int b)
{
printf("静态成员函数:%d\n", a + b);
}
//仿函数
void operator ()(int a, int b)
{
printf("仿函数(类对象):%d\n", a + b);
}
};
int main()
{
int a = 1;
int b = 2;
//lambda表达式
auto lam = [](int a, int b) {printf("lambda表达式:%d\n", a + b); };
Function = lam;
std::thread t1(Function, a, b);
t1.join();
//函数指针
void(*p)(int, int) = fun2;
Function = p;
t1 = std::thread(Function, a, b);
t1.join();
//静态成员函数
Function = &A::fun2;
t1 = std::thread(Function, a, b);
t1.join();
//成员函数
A c;
Function = std::bind(&A::fun1,c, std::placeholders::_1, std::placeholders::_2);// 此时将对象c指定为对象实例
t1 = std::thread(Function,a,b);// 这里不用将c传进去了
t1.join();
//仿函数
A d;
Function = d;
t1 = std::thread(Function, a, b);
t1.join();
}
输出结果:
lambda表达式:3
函数指针:3
静态成员函数:3
类成员函数:3
仿函数(类对象):3
可以用到的初始化的方式大概就这样几种,都得用到可调用对象。
2.移动构造函数
首先我们要明白移动构造函数的用途,是把一个thread对象的线程转移到构造出来的thread对象上,可以通俗的理解成一次性赋值,过后被移动的thread对象将不在执行线程。但是我们不也能直接将被移动thread对象作为参数传进去,需要用std::move(),将它转换为右值。
#include
#include
void fun()
{
printf("I love China\n");
}
int main()
{
std::thread t(fun);
std::thread t1(std::move(t));
t1.join();
}