When the operator()() overload function of the function template is defined as the thread function of thread()

Directory-Three forms of starting thread function

1. When passing in ordinary function pointers as thread functions (introducing the precautions for passing in references)

2. When passing in a function object as a thread function (calling the operator()() overloaded function that declares the function template)

1. Call the class directly

2. Instantiate the class object

3. When passing an anonymous function as a thread function


Simple understanding of std::thread()

When we do concurrent work, we need to use std::thread() to create, manage and synchronize threads. First of all, we need to know the parameter list composition of std::thread()

The first parameter: three forms that can be used as thread functions

function pointer

Function objects (operator()() overloaded functions, also called functors) – heavy and difficult points

Lambda anonymous expression.

Other parameters: equivalent to the variable parameter list, the actual parameters are passed in according to the parameter list of the calling function

Here we mainly explain the precautions and implementation methods when passing in thread functions

In particular:

If you want to pass a reference, you must call std::ref() to convert the incoming address into a reference, as described in the following code

1. When passing in ordinary function pointers as thread functions (introducing the precautions for passing in references)

#include <iostream>
#include <thread>

using namespace std;
/*
    Brothers, study char const*const & amp; str carefully. What are the functions of the two const?
    Remember the mantra: Left Quantitative, Right Directional
    1. The first const: indicates that str is a pointer to a constant character, that is, the content of the character pointed to by the pointer cannot be modified.

    2. The second const: Indicates that str is a constant reference, that is, the value of str cannot be modified inside the function. At the same time, using constant references can avoid
       Avoid unnecessary copying and improve code efficiency.
*/
void test(char const*const & amp; str) {//Incoming char* type reference
cout << "Correctly use std::ref() conversion, the address of p in the test function = "<< & amp;str << " The transmitted string = " << str << endl;
}
void test1(char const*const & str) {
cout << "does not use std::ref() conversion, the address of p in the test function = " << & amp;str << " the transmitted string = " << str << endl;
}

int main(int argc, char* argv[]) {
char str[11] = "Come on Aoli to";
char* p = str;
//The following are all about the address of p itself, not the string of str
cout << "p address of the main function = "<< & amp;p << endl;

/*
Notice:
     If you want to successfully pass in references in thread(), you must follow these two steps, both of which are indispensable
     The first step: std::ref() is used to wrap an object (address) into a reference type object

     Step 2: Of course, if you want to pass a reference, the test parameter list should also be declared to take & amp;, char* const & amp; str, if you do not declare this & amp;, then
            std::ref() loses its meaning
*/

//The case of using std::ref()
std::thread first(test, std::ref(p));
first.join(); //join() means to execute the child thread first, that is, test(), and then continue to execute the following part.
//The case where std::ref() is not used
std::thread second(test1, p);
second.join(); //Be sure to choose the execution method of the thread, otherwise the program will throw an exception
return 0;
}

2. When passing in a function object as a thread function (call the operator()() overloaded function that declares the function template)

Two ways to pass in function objects

1. Call the class directly, without initializing the object, you need to declare the template on the entire mythread class

2. To instantiate a class object, justtemplate is declared above the operator()() function

The implementation codes of the two methods will be given below, and the values will be passed

1. Call the class directly

#include <iostream>
#include <thread>

using namespace std;

template<typename T> //function template
class mythread {
public:
explicit mythread() { //constructor
//cout << "default gaozao is use" << endl;
}
mythread(const mythread & amp; p) { //copy constructor
//cout << "copy thread" << " address = " << & amp;p << endl;
}
~mythread() { //destructor

}

void operator()(T number){ // functor
cout<<number<<endl;
}


private:

};

int main(int argc, char* argv[]) {
    // Next, our purpose is to pass the function object to the thread as the first parameter, assuming that the incoming actual parameter type is int
    int number = 666;
    std::thread first(mythread<int>(),number); //Here is the value transfer, to pass the reference follow the method in my code above
    first. join();
//Usual initialization is written like this
    //mythread<vector<int>::iterator, int>()(begin,array.end(), results[reality - 1]);
\t
    return 0;
}

2.Instantiate class object

#include <iostream>
#include <thread>

using namespace std;

class mythread {
public:
explicit mythread() { //constructor
//cout << "default gaozao is use" << endl;
}
mythread(const mythread & amp; p) { //copy constructor
//cout << "copy thread" << " address = " << & amp;p << endl;
}
~mythread() { //destructor

}
template<typename T> //function template
void operator()(T number) { // functor
cout << number << endl;
}


private:

};

int main(int argc, char* argv[]) {
// Next, our purpose is to pass the function object to the thread as the first parameter, assuming that the incoming actual parameter type is int
int number = 666;
mythread obj;
//here number is passed by value, if you want to pass a reference, follow the method in my code above
std::thread first( &mythread::operator()<int>, &obj, number);
first. join();
//Usual initialization is written like this
    //obj(number);
    //or
//obj. operator() < int > (number);

return 0;
}

In the second method, std::thread first( & amp;mythread::operator(), & amp;obj, number); This code is very important

In the above example, `Mythread` is a class object that overloads the function template `operator()()`. The first parameter of the constructor of `std::thread` is a pointer to a member function, and `&Mythread::operator()` is used here to specify the `operator()` function as a thread function. The second parameter is a pointer to a class object, and `&obj` is used here to specify `obj` as a class object. Finally, `number` is the argument passed to the `operator()` function.

It should be noted that if the member function of the class object is a non-static member function, then the pointer of the class object needs to be passed as the second parameter to the `std::thread` constructor. If the member function is a static member function, the class name can be passed as the first argument to the `std::thread` constructor. (Operator overloading functions cannot be static functions)

3. When passing an anonymous function as a thread function

#include <iostream>
#include <thread>

using namespace std;

int main(int argc, char* argv[]) {
int a = 44;
cout << "address of a in the main function = "<< & amp; a << endl;

//It's very interesting here. There are two ways for anonymous functions to access members. The final effect is the same, and both realize the reference to a
\t
//1.thread(), after calling the anonymous function, fill in the actual parameters and pass them to the anonymous function
std::thread t1([](int & amp; a) {std::cout << "The address of a in method 1 = " << & amp;a << endl; }, std::ref (a));
t1. join();
//2. Direct access to members by controlling the permissions of [], you can query Baidu for a more comprehensive understanding of the specific permissions of []
std::thread t2([ & amp;]() {std::cout << "Address of a in method 2 = " << & amp;a << endl; });
t2. join();
\t
return 0;
}