https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68784
--- Comment #6 from Wang Xuancong <xuancong84 at gmail dot com> --- You are right! I have tested myself. MSVC outputs 0 instead of crashing (crashing is what we expected), it is accepting compilation but not doing the job correctly, that it passes a temporarily created copy of the object instead of the reference of the original object. Since g++ gives a compilation error, but MSVC accepts the syntax but fails silently. So in the end, g++ still better than MSVC, I take back my original claim. However, I do not agree with "the standard requires std::thread to copy its arguments for safety reasons, to avoid silently forming dangling references to stack variables". Not all programmers are ignorant. Whether to pass in the reference of the original object or the temporarily created object, can be made clear by the programmer when they specify the arguments for the thread function, e.g., void thread_add(unordered_map<int, int>& ht, int from, int to); void thread_add(unordered_map<int, int> ht, int from, int to); The programmers should know what they are doing, and the difference between the above two thread function declarations. And they should also know that all local objects are stored on the stack, if the function returns, all local objects are destructed. Thus, the thread creator function can return only after all threads finished, if the thread function will ever access the creator function's local objects.