The temporary object is released per the standard, leading to undefined behavior. An implementation may do anything, including keeping the object's bytes in stack memory until they are overwritten, which allows your code to (incorrectly) work.
When I disassembled the binary produced by my compiler (clang++ 9.0.1) I noticed that the stack pointer was not "regressed" when the block containing data
ended, thus preventing it from being overwritten when
cout << "main loop" << endl;
resulted in function calls.
Furthermore, due to short string optimization, the actual ASCII "123" is stored within the std::string
object itself and not in a heap-allocated buffer.
The draft standard says the following:
6.6.4.3 Automatic storage duration
Block-scope variables not explicitly declared static, thread_local, or extern have automatic storage duration. The storage for these entities lasts until the block in which they are created exits.
Experimentally, if I make the string long enough to disable short string optimization, the program still silently works since the bytes in the buffer happen to remain intact in my experiment. If I enable ASAN, I get a correct heap use-after-free warning, because the bytes were freed at the end of the string's lifetime, yet were accessed through an illegal use of a pointer to the now-destructed string.