My understanding is that the rhs of line 1 construct only a temporary object. getMe() then return the reference of this temp object and bind it to thg (as a lvalue reference). After line one, the temp object is really destroyed (hence the first output line). At this point thg is really binding to a destroyed, invalid object. But somehow the 2nd line still prints the correct value of 10 is because the memory storage is not yet corrupted (still holding the previous value). Is this correct?
The second line print the correct value by pure luck. It just so happens that between destroying the object and printing the value it contained, that memory didn't get overwritten. It is undefined behavior - the program may crash, you may get a garbage value, or as you saw it may work.
Your replies are more or less what I thought too. But things can get a bit more subtle here.
Note that in construct_Thing10(), the return value is Thing, not a pointer nor a reference. So in principle, a Thing object is constructed in construct_Thing10()'s stack, and then copied to another Thing object in the main()'s stack. thg is really bound to a temp object in main()'s stack. This is getting even more cryptic because, with more experiments, I didn't really see the copy constructor being executed, perhaps due to the return value optimization, whereby the copy construction is avoided by creating the local copy of Thing in the calling function's stack.
Now if I change the 1st line to:
Thing &&thg=construct_Thing10();
thg should still bind to the temp object on main()'s stack, but the output lines are reverse:
member=10
destroying Thing (i=10)
So the confusing part is that in both cases, thg was binding to a temp object on main()'s stack. But if thg is defined as Thing &, the temp object is destructed right after the assignment; whereas if thg is defined as Thing &&, the temp object is kept alive until the end of main().
This expression creates and returns a temporary object: construct_Thing10()
This extends the temporary object's lifetme: Thing &&thg=construct_Thing10();
This also extends the temporary object's lifetime: const Thing &thg=construct_Thing10();
This expression returns a reference to the temporary object, which becomes a dangling reference once the expression finished: construct_Thing10().getMe(). Binding this reference to another reference does nothing for the object's lifetime.