thread in C++

In C++ 11 we can create threads by creating objects of std::thread class. Each of the std::thread object can be associated with a thread.
We can attach a callback with the std::thread object, that will be executed when this new thread starts. These callbacks can be,
* Function Pointer
* Function Object
* Lambda function
```
#include <iostream>
#include <thread>
using namespace std;

void f() {
    cout<<"f()"<<endl;
}

class c{
public:
    void operator()() {
        cout<<"c()"<<endl;
    }
};

auto lambda=[]{ cout<<"lambda"<<endl; };
 
int main()  
{
    thread tf(f);
    tf.join();    
    
    thread tc((c()));
    tc.join();
    
    thread tl(lambda);
    tl.join();
    return 0;
}
```
* Once a thread is started then another thread can wait for this thread to finish. For this another thread need to call join() function on this thread object.
* Detached threads are also called daemon / Background threads.  To detach a thread we need to call detach() function on thread object.
* Before calling join() or detach() we should check if thread is joinable by call joinable()
    * When a join() function is called on an thread object, then when this join() returns, then that thread object has no associated thread with it. In case again join() function is called on such object then it will cause the program to terminate.
    * Calling detach() makes the thread object not linked with any thread function. In that case calling detach() function twice on a thread object will cause the program to terminate.
    * If neither join or detach is called with a thread object that has associated executing thread then during that object’s destructor it will terminate the program.
    * We should not forget call either join() or detach() in case of exceptions. We should use Resource Acquisition Is Initialization (RAII).
* To Pass arguments to thread’s associated callable object or function just pass additional arguments to the std::thread constructor. 
    * By default all arguments are copied into the internal storage of new thread.
    * Don’t pass addresses of variables from local stack to thread’s callback function. Because it might be possible that local variable in Thread 1 goes out of scope but Thread 2 is still trying to access it through it’s address. In such scenario accessing invalid address can cause unexpected behaviour.
    * Be careful while passing pointer to memory located on heap to thread. Because it might be possible that some thread deletes that memory before new thread tries to access it. In such scenario accessing invalid address can cause unexpected behaviour.
    * Arguments are copied to new threads stack, so for reference, even if thread callback accepts arguments as reference but still changes done on it are not visible outside the thread. Its because value in the thread callback is reference to the temporary value copied at the new thread’s stack.
        * To fix this, use std::ref().