Your code refers to an object outside of its lifetime, which is a behaviour
that was intentionally left undefined in the standard, and regarding which
the standard imposes no requirements.
Having said that, it would be nice if compilers at least threw a warning
about that, but I suspect that catching this sort of problem is no easy
task.
In terms of run-time efficiency, it is proably cheaper just to make it work
than to catch violations. That is to say, allow these local objects
to persists while they are reachable.
The reasoning is that if you want to be able to detect all abuses like
this at run time, then for each local object whose address might escape
from the function, you have to record that address in some permanent "bad
pointer" database, and not reuse that address for any newly created object.
So that this database doesn't run you out of memory, you will need garbage
collection to discover those bad pointers that no longer occur in the program's
state and can be purged.
So you have GC, and you have costly run-time checks guarding the uses
of pointers: two sources of performance hits.
But once you let those object persist without being reused, and you
have GC, then you just might as well let those pointers be valid
and dispense with the run-time checks.
There is nothing "morally" wrong with using an object that was created in a
function that returned, and decriminalization of activities that are not
actually wrong is usually cheaper than enforcement.