std::thread.join has three functions I can think of off-hand and some others:
a) Encourages continual creating/terminating/destroying of threads, so hammering performance and increasing the probabilty of leaks, thread-runaway, memory-runaway and general loss-of-control of your app.
b) Stuffs GUI event-handlers by enforcing unwanted waits, resulting in unresponsive 'hourglass apps' that your customers will hate.
c) Causes apps to fail to shutdown because they are waiting for the termination of an unresposive, uninterruptible thread.
d) Other bad things.
I understand that you are new to multithreading, and I wish you the best with it. Also, consider that I've had a lot of Adnams Broadside tonight, but:
Join(), and it's friends in other languages like TThread.WaitFor, (Delphi), are to efficient multithreading like Windows ME was to operating systems.
Please try hard to progress and come to understand other multithreaded concepts - pools, tasks, app-lifetime threads, inter-thread comms via producer-consumer queues. In fact, almost anything except Join().