Looks to me like that's creating a reference to a Temporary String object that's created by 'String("hello") + " " + String("world");'
After that statement completes, that Temporary object is destroyed and the reference to it is no longer valid.
I hoped to be able to use "#define let auto const&" and consistently use "let" where an immutable reference/value is used. I hoped the compiler realizes that the temporary value created is referenced and should not be "freed".
Worth a try though considering the esthetics of the source with a ubiquitous "let" for any immutable reference/value. Might also automatically avoid making copies of objects when not necessary ...
I agree that OP's code should work as expected, and something fishy is going on.
This, on the other hand, is not valid. str1 is a pointer to a string that will have been destroyed by the time you use it. Only the lifetime of the pointer is extended, which is not what you need.
In a generic function, you may not know whether something is a reference or a value. In that case, you might want to hold on to it in a variable, but not create unnecessary copies, either because of overhead of copying/moving, or because you might care about the address of the referenced object.
For example, if you have a user-provided function f, you'd use const auto &tmp = f();.
By binding the unknown return value to a const auto & or a universal auto &&, you won't copy it if f returns a reference.