cpp11thread实现类成员函数线程的三种方法

⌚Time: 2023-05-17 14:21:25

👨‍💻Author: Jack Ge

使用C++11的thread类创建线程,他的构造函数


template <class Fn, class... Args>explicit thread (Fn&& fn, Args&&... args);

第一个参数是线程函数地址,后面的是传递给线程函数的参数

回调函数是通过指针调用的函数,对于Win32API,使用CreateThread创建的线程函数就是回调函数。他的lpStartAddress参数指向线程函数地址。lpParameter是传递给线程函数的参数。

C++类成员函数使用时,都会隐式传递一个this指针给该函数,this指针指向该类的对象。函数体可以通过显示调用该指针或直接访问类内成员。如果将类成员函数作为线程函数,会因为回调函数参数不匹配出错

正确的C++11类成员函数线程创建方法


t[i] = thread(std::mem_fn(MyClass::thread_func), Object, args..);

向他的参数传递一个对象指针,如果调用线程的函数也是类成员函数,那么传入的是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++这不仅仅是在线程中需要注意的,在其它地方也是一样)