2. C++ uses Thread thread parameter passing problem

1. Description

Passing parameters in the sub-thread function actually means that the constructor of the Thread class copies the passed parameters and copies them to the independent memory of the thread. Even if the parameters are in the form of references, they can also be accessed in the new thread. If The type of parameter passing is inconsistent, and the type will be implicitly converted in the context of the thread . However, special attention needs to be paid when the passed parameter is a pointer type, and there may be problems, see below for details.

2. Ordinary parameter passing

If there is no need to change the passed parameters in the child thread, then pass the parameters normally when passing the parameters. To avoid misoperation, you can use the const keyword to modify:

#include <iostream>
using namespace std;

#include <thread>

void myprint(const string s)
{
    
    
    cout << s << endl; 
}

int main()
{
    
    
    string s = "xiaoming";

    thread mythread(myprint, s);

    mythread.join();

    std::cout << "主线程:"<<s<<endl;

    return 0;
}

3. Pass by reference (using ref)

If you want to modify the data passed in the main thread in the child thread, you need to use the **std::ref()** function:

#include <iostream>
using namespace std;

#include <thread>

void myprint(string& s)
{
    
    
    
    s = "xiaohong......";
    cout <<"子线程:" << s << endl;
    
}

int main()
{
    
    
    string s = "xiaoming";

    thread mythread(myprint, ref(s));

    mythread.join();

    std::cout << "主线程:"<<s<<endl;

    return 0;
}

4. Pass pointer variable

Although the Thread class converts parameter types, it still needs to perform explicit type conversion when encountering pointer variables , otherwise problems will occur.
Dangling pointer : When the pointed object is released or recovered, but no modification is made to the pointer, so that the pointer still points to the memory address that has been reclaimed, in this case, the pointer is called a dangling pointer

#include <iostream>
using namespace std;

#include <thread>

void myprint(const string& mbuffer)
{
    
    
    cout <<"子线程:" << mbuffer << endl;
}

int main()
{
    
    
    char buffer[] = "this is a test....";

    thread mythread(myprint,string(buffer));//使用string进行显式类型转换,避免悬垂指针

    mythread.join();

    std::cout << "主线程:运行结束...."<<endl;

    return 0;
}

4. Pass custom classes

A variable is defined using the keyword mutable in the custom class , which can facilitate the change operation. To actually transfer the custom class object to the child thread, the Thread constructor will call the copy constructor of the custom class , and the class actually transferred to the child thread is not the original class object in the main thread:

#include <iostream>
using namespace std;

#include <thread>

class A
{
    
    
public:
    A(int a) :m_i(a)
    {
    
    
        cout << "[A::A(int a )构造函数执行]" << this << "threadid = " << this_thread::get_id() << endl;
    }
    A(const A& a) :m_i(a.m_i)
    {
    
    
        cout << "[A::A(const a )拷贝构造函数执行]" << this << "threadid = " << this_thread::get_id() << endl;
    }
    ~A()
    {
    
    
        cout << "[A::~A( )析构函数执行]" << this << "threadid = " << this_thread::get_id() << endl;
    }
public:
    mutable int m_i;
};

void myprint(const A& a)//这里虽然使用了引用&,但输出结果发现并非是真正的引用,实际上引用的是拷贝构造函数复制出来的另一份对象a
{
    
    
    a.m_i = 2;//对变量进行更改
    cout <<"子线程入口函数(类中的变量):" << a.m_i << endl;
}


int main()
{
    
    
    int mvar = 1;

    A a(mvar);

    thread mythread(myprint,a);

    mythread.join();

    cout << "主线程(类中的变量):" << a.m_i << endl;//输出原始类对象中的m_i变量

    std::cout << "主线程:运行结束...."<<endl;

    return 0;
}

The result of the operation is as follows: It is found that the variable value of m_i output twice is different, and the copy constructor of class A is executed.
insert image description here
If you want to make a real reference to the custom class, you need to use the std::ref() function
to modify the above code show as below:

thread mythread(myprint,std::ref(a));//传递参数时使用 ref 函数才能做到整正的引用

At this time, if you output the result again, you will find that the copy constructor in the custom class is not called
insert image description here

5. Pass custom class member functions

Pay attention to the use of references for parameter passing

#include <iostream>
using namespace std;

#include <thread>

class A
{
    
    
public:
    A(int a) :m_i(a)
    {
    
    
        cout << "[A::A(int a )构造函数执行]" << this << "threadid = " << this_thread::get_id() << endl;
    }
    A(const A& a) :m_i(a.m_i)
    {
    
    
        cout << "[A::A(const a )拷贝构造函数执行]" << this << "threadid = " << this_thread::get_id() << endl;
    }
    ~A()
    {
    
    
        cout << "[A::~A( )析构函数执行]" << this << "threadid = " << this_thread::get_id() << endl;
    }
    //添加成员函数
    void thread_work(int num)
    {
    
    
        cout << "[成员函数thread_work执行了....]" << endl;
    }

public:
    mutable int m_i;
};

void myprint(const A& a)
{
    
    
    a.m_i = 2;//对变量进行更改
    cout <<"子线程入口函数(类中的变量):" << a.m_i << endl;
    
}


int main()
{
    
    
    int mvar = 1;

    A myobj(mvar);

    //第一个参数是成员函数名,第二个参数是类对象名(注意使用引用的方式),第三个参数是成员函数需要的参数
    thread mythread(&A::thread_work,&myobj,15);

    mythread.join();

    std::cout << "主线程:运行结束...."<<endl;

    return 0;
}

6. Pass smart pointers (using std::move() function)

#include <iostream>
using namespace std;

#include <thread>

void myprint(unique_ptr<int> pzn)
{
    
    
    
}

int main()
{
    
    
    unique_ptr<int> mypzn(new int(100));

    thread mythread(myprint,std::move(mypzn));

    mythread.join();

    std::cout << "主线程:运行结束...."<<endl;

    return 0;
}

Guess you like

Origin blog.csdn.net/FY_13781298928/article/details/130216142