What is the difference between async([](){}) and thread([](){}).detach()?

I know a good answer was given to your question but if we were to change your question a little something interesting would occur.

Imagine you kept the future returned by the async and didn't detach the thread but instead made a variable for it like this,

Asynchronous code

auto fut=std::async([]() { ... });
std::thread th([]() { ... });

Now you have the setup to what makes these 2 constructs different.

th.join()//you're here until the thread function returns

fut.wait_for(std::chrono::seconds(1)); //wait for 1 sec then continue.

A thread is an all or nothing thing when joining it where as an async can be checked and you can go do other stuff.

wait_for actually returns a status so you can do things like this.

 int numOfDots = 0;
 //While not ready after waiting 1 sec do some stuff and then check again
 while(fut.wait_for(std::chrono::seconds(1)) !=  std::future_status::ready)
 {
    (numOfDots++)%=20; 
    //Print status to the user you're still working on it.
    std::cout << "Working on it" <<std::string(numOfDots,'.')<<"\r"<<std::flush();
 }
 std::cout << "Thanks for waiting!\nHere's your answer: " << fut.get() <<std::endl(); 

std::async  ([]() { ... });            // (1)
std::thread ([]() { ... }).detach ();  // (2)

Most often when std::async is being discussed the first thing noted is that it's broken, the name implies something which doesn't hold when the returned value isn't honored (assigned to a variable to be destructed at the end of the current scope).

In this case the brokenness of std::async is exactly what is going to result in a huge difference between (1) and (2); one will block, the other won't.


Why does std::async block in this context?

The return-value of std::async is a std::future which has a blocking destructor that must execute before the code continues.

In an example as the below g won't execute until f has finished, simply because the unused return value of (3) can't be destroyed until all work is done in the relevant statement.

std::async (f); // (3)
std::async (g); // (4)

What is the purpose of std::thread (...).detach ()?

When detaching from a std::thread we are simply saying; "I don't care about this thread handle anymore, please just execute the damn thing."

To continue with an example similar to the previous one (about std::async) the difference is notably clear; both f and g will execute simultaneously.

std::thread (f).detach ();
std::thread (g).detach ();