使用C++11的thread类创建线程,他的构造函数
第一个参数是线程函数地址,后面的是传递给线程函数的参数
回调函数是通过指针调用的函数,对于Win32API,使用CreateThread创建的线程函数就是回调函数。他的lpStartAddress参数指向线程函数地址。lpParameter是传递给线程函数的参数。
C++类成员函数使用时,都会隐式传递一个this指针给该函数,this指针指向该类的对象。函数体可以通过显示调用该指针或直接访问类内成员。如果将类成员函数作为线程函数,会因为回调函数参数不匹配出错
正确的C++11类成员函数线程创建方法
向他的参数传递一个对象指针,如果调用线程的函数也是类成员函数,那么传入的是this指针
代码
#include <thread>
#include <iostream>
//member函数thread
class MT1{
public:
MT1(int arg):num(arg){
}
void start_t(int arg){//成员函数启动线程,传入参数为this
std::thread t(&MT1::start, this, arg);
t.detach();
}
void start(int arg){
while(1){
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout<<"thread MT1 running,arg "<<arg<<" number "<<num<<"\n";
}
}
int num;
};
int main(){
MT1 mt1(3);
mt1.start_t(4);
MT1 mt11(5);
std::thread t(MT1::start,&mt11,6);//启动类成员函数线程,传入对象指针
t.detach();
system("pause");
return 0;
}
输出
g++ t1.cpp -std=c++11
a
请按任意键继续. . . thread MT1 running,arg thread MT1 running,arg 6 number 5
4 number 3
thread MT1 running,arg 6 number 5
thread MT1 running,arg 4 number 3
thread MT1 running,arg 6 number 5
thread MT1 running,arg 4 number 3
thread MT1 running,arg 6 number 5
thread MT1 running,arg 4 number 3
还可以将类成员函数设置静态成员函数。不属于任何一个对象,属于整个类。没有this指针。可以像全局函数 一样创建线程。缺点是类静态成员函数只能访问类静态成员变量。
#include <thread>
#include <iostream>
//static函数thread
class MT3{
public:
MT3(){
}
static void start(int arg){
while(1){
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout<<"thread MT3 running,arg "<<arg<<" number "<<num<<"\n";
}
}
static int num;
};
int MT3::num = 76;
int main(){
std::thread t(&MT3::start,7);
t.detach();
system("pause");
return 0;
}
请按任意键继续. . . thread MT3 running,arg 7 number 76
thread MT3 running,arg 7 number 76
thread MT3 running,arg 7 number 76
thread MT3 running,arg 7 number 76
thread MT3 running,arg 7 number 76
thread MT3 running,arg 7 number 76
还可以在类中声明友元函数,友元函数可以访问类中的成员变量
#include <thread>
#include <iostream>
//友元函数thread
class MT2;
void start_MT2_t(MT2 *arg);
class MT2{
public:
MT2(int arg):num(arg){
}
friend void start_MT2_t(MT2 *);
int num;
};
void start_MT2_t(MT2 *arg){
while(1){
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout<<"thread MT2 running,number "<<arg->num<<"\n";
}
}
int main(){
MT2 mt2(1);
std::thread t(&start_MT2_t, &mt2);
t.detach();
system("pause");
return 0;
}
请按任意键继续. . . thread MT2 running,number 1
thread MT2 running,number 1
thread MT2 running,number 1
thread MT2 running,number 1
使用类成员函数线程需要注意的地方:
1.执行线程函数的对象在线程结束之前不能被销毁。否则会导致线程崩溃。因此最好使用new在堆中分配对象空间,防止对象当前作用域结束后被自动释放。
2.传入的参数如果是变量而不是指针,线程所使用和修改的是该变量的拷贝而不是变量本身(对于c++这不仅仅是在线程中需要注意的,在其它地方也是一样)