Why does it (seem to) work?
In your second example, there is no thread associated with the std::thread object t. As a result, t.joinable() is false when it is called, and no join is made. But you then move assign a thread to t and return from main(). As t is a local object, it's destructor is called:
If *this has an associated thread (joinable() == true), std::terminate() is called.
So terminate is called, but this looks pretty much as a normal situation since you do not expect anything else to happen afterwards in your snippet.
But why doesn't it work as you think?
If you want to understand the real problem of your second code snippet, I suggest rather to move all the code of main to a separate function, like:
int my_strange_test()
{
thread t;
if (true == t.joinable())
{
t.join();
}
t = std::thread(func);
return 0;
}
int main()
{
cout << "Launch my test" << endl;
my_strange_test();
cout << "My test successfully finished" << endl;
}
Here you'll see that the second message is never reached because of the abrupt termination (online demo).
How to get it right?
If you replace the testing function with your first snippet, it will work as expected. Ok, as you have an infinite loop, the thread will never finish what it does, so the join will wait forever. But just put an upper limit to the number of iterations and it'll be fine, online demo).
Alternatively, you may want the main thread to control when to finish the loop. You may then go for something like:
void func(atomic<bool>& on_off)
{
while (on_off)
{
cout << "Calling func()" << endl;
}
}
int my_strange_test()
{
thread t;
atomic<bool> run{true};
t = std::thread(func, std::ref(run)); // tricky !
this_thread::sleep_for(10ms); // do something else
if (true == t.joinable())
{
run = false; // tell thread to finish iterations
t.join(); // and wait that it returns
}
return 0;
}
Online demo
funcnever return, so in the first caset.join()will get stuck forever. In the second case thejoinwill never be called because at that pointt.joinable()will be false. You can see all this in a debugger.join()called in the second snippet.joinable, assigned it cannot be. godbolt.org/z/hf18Gh7EE you should see if proof you require. Simpler you should get. Easier to read,if (t.joinable())is.